《C和指標》讀書筆記(5)
宣告:該讀書筆記摘抄自《C和指標》——Kenneth A.Reek (著) 徐波(譯)。為了克服自己走馬觀花,提高閱讀和學習效率,決定將自己在讀書過程中遇到的一些知識點加以摘抄和總結備忘,在此感謝原書作者和翻譯。
一、有助於理解C語言指標的幾個基礎概念
1、左值:賦值號“=”左邊的運算元; 右值:賦值號“=”右邊的運算元。
2、變數的值:分配給該變數的記憶體位置儲存的值,對指標變數來說它的值就是某個記憶體地址;
3、變數的地址:編譯器為該變數分配的一個記憶體位置,用於儲存變數本身,注意變數的地址和變數的值的區別,我想說的是對於普通變數很好理解,難點在於多級指標。
4、間接訪問(也叫解引用):一個指標訪問它所指向的地址,間接訪問操作符 “ * ” 。注意:間接訪問僅僅是指定了一個特定的記憶體地址而已。
5、當變數作為左值使用時,它表示一個記憶體地址; 當變數作為右值使用時它表示該變數裡面儲存的內容。真正地理解了這一點有助於理解指標的複雜應用和原理。
舉個例子:
int a = 1, b = 2, c = 8,*p = &b;
*p = *p +1;
printf("b = %d\n", b);
p = p + 1;
printf("*p = %d\n", *p);
第一個printf結果很好分析,*p作為右值的時候,最終的結果是取出了p所指向的地址的內容,但是這裡麵包含了兩個過程,第一步:*p表示間接訪問,這一步確定了變數b,至於是訪問b的地址還是它儲存的內容,暫時還不清楚;第二步:*p在表示式中是個右值,因此編譯器會確定訪問它的內容。注意:左值和右值得區分是由編譯器自動完成的。因此,第一個列印結果是 3 。
現在來看第二個,這整個例子是我自己寫的,在linux-gcc下測試。 其實在我寫的這個例子中p = p + 1;這個語句其實是非法的,因為指標的算術運算僅僅在記憶體地址連續分配的陣列中才有意義,這裡我僅僅是為了舉例子演示而已。
注:在上例中,我之所以在變數b前面定義變數a是為了保證讓p + 1合法,也是為了驗證棧的生長方向;在b的後面定義變數c僅僅是為了驗證棧的生長方向。
二、指標表示式
這部分內容在筆試題目裡面出現的次數很多,很容易混淆,究其原因主要是沒有弄清楚指標運算的本質過程,一條簡單的C語句有可能是好幾條彙編指令的集合過程,如果有條件可以從彙編的角度去理解。
這裡定義幾個實驗變數:char a = '1',b = '2',c = '3', *p = &b;後面就用它們來舉例說明幾個指標表示式的執行過程:
1、 p++
第一步:該表示式首先返回指標變數p的一份拷貝,該拷貝將會被存放到記憶體的某一個地方以便後面使用,注意,這裡說“某一個”是因為我們並不能確定具體的儲存位置,這是一個表示式內部計算的中間過程,存放位置也是一個臨時位置,這一點解釋了為什麼該指標表示式不能用作左值——因為拷貝值的儲存位置不確定。因此p++只能充當右值。第二步:表示式返回一份拷貝後,將指標變數p自身的值加1。可以看出,該表示式實際上是執行了兩個過程,在第一步執行完了以後,如果該指標的拷貝會被用到,例如 char *q = p++;那麼該拷貝將會賦值給指標變數q。如果該拷貝不會被用到,例如 只有 一句p++;語句,那麼該拷貝值將會被簡單丟棄。
2、++p
第一步:該表示式首先將指標變數p的值加1,;第二步:產生一份加1之後的拷貝,產生的這份拷貝也將會被儲存與記憶體的某一個位置留待後用或者不用被簡單丟棄,這一點也解釋了改表示式同樣不能作為左值使用。
3、*++p
++優先順序高於間接訪問符,先執行++p,++p的執行過程已經解釋過了,它的結果是增值之後的指標的拷貝,然後間接訪問操作符再作用於該指標拷貝上,這樣得到的結果將是對增值後的指標的間接訪問,它可以作為左值也可以作為右值,具體說明見第一部分第5條。
4、*p++
這個表示式會引起誤解:++優先順序高於間接訪問符,因此先執行p++,然後間接訪問符作用於增值後的指標變數。這是錯誤的。 ++優先順序高於間接訪問符這句話沒錯,先執行p++也沒錯,錯就錯在了間接訪問符的作用物件上,它其實是間接訪問增值前的指標。表示式執行過程分解:第一步:++操作符產生指標變數p的一份拷貝先暫時存放到某個位置;第二步:++操作符增加指標變數p的值;第三步:在指標變數p的拷貝上執行間接訪問操作,注意是在拷貝上執行間接訪問操作,即間接訪問的是增值前的指標。它可以作為左值也可以作為右值,具體說明見第一部分第5條。
5、++*p
++和間接訪問符的結合性從右到左,首先執行對p的間接訪問,然後將間接訪問的內容增1,最後表示式返回一份內容增1後的拷貝。只能做右值,不能做左值。理由同p++。
6、++*++p
三個操作符結合性都是從右到左。*++p已經分析過,它返回對增值後的指標的間接訪問。然後對*++p間接訪問的內容進行增1操作,最後返回內容增1後的值的拷貝。只能做右值,不能做左值。理由同p++。
7、++*p++
*p++已經分析過了,它的結果是間接訪問增值前的指標。然後對間接訪問的內容進行增1操作,返回內容增1後的值的拷貝。只能做右值,不能做左值。理由同p++。
三、指標的算術運算和關係運算
1、指標的算術運算有兩種形式,標準定義這兩種定義只能用在連續儲存的同一陣列中。第一:指標加上(或者減去)一個整數,此時需要考慮步長;第二:指標減去指標,這裡特別注意,兩個指標相減時得到的結果是相距的距離,即兩指標相減後還要除以步長,它是指標加減法的逆運算。
2、關係運算
> >= < <= !=
前面4個只能用在同一個陣列中比較, !=可以用於任意兩指標比較。
花了三個多小時來理清指標的思路,儘量表達清楚和全面,都已經深夜了,睡了。
以上是第六章的摘抄和總結,未完待續。。。。。