天天看點

【 C 】對左值與右值的一些個人思考

今天重溫C語言的指針,看的書是《C和指針》,關于左值和右值以及指針表達式的内容看得甚是迷惑與煎熬,怎麼會這麼難了解,指針表達式又是作為左值又一會作為右值,而且二者有着不一樣的含義,為什麼當年學習C語言的時候沒有遇到這些頭疼的問題呢?這就是沒有學好C的原因吧。

功夫不負有心人,認真思考,對比總結,竟有些頭緒,記錄下來吧。以免以後又忘了沒有參考。

先談談左值與右值的定義吧。

左值就是那些能夠出現在指派符号左邊的東西;是以,右值就是那些可以出現在指派符号右邊的東西。

舉個例子:

a = b + 25;

a是一個左值,因為它辨別了一個可以存儲結果值的地點;b + 25是一個右值,因為它指定了一個值。

它們可以互換嗎?也就是 b + 25 = a;

原先用作左值的a,此時也可以用作右值,因為每個位置包含一個值。然後 b + 25不能作為左值,因為它并未辨別一個特定的位置。是以,這條指派語句是錯誤的。

注意,當計算機計算b+25時,它的結果必然儲存于機器的某個地方。但是,程式員并沒有辦法預測該結果會存儲于什麼地方,也無法保證這個表達式的值下次還會存儲于那個地方。其結果是,這個表達式不是一個左值。基于同樣的道理,字面值(常數)也都不是左值。

看了上面的總結,是不是有這樣的感覺,變量可以作為左值,而表達式不能作為左值?

這是一種錯覺,事實情況下并非如此,下面就專門總結這種情況。

第一個例子:

int a[30];
...
a[b+10] = 0;      

[]是下表引用操作符,是以左邊實際上是一個表達式,但它卻是一個合法的左值,因為它辨別了一個特定的位置,這個數組的某個特定的位置。

第二個例子:

int a, *p;
...
p = &a;
*p = 20;      

第一條指派語句自然不必多說,指向整型變量的指針變量指定了一個特定的位置存放變量a的位址,p可以作為左值;

第二個指派語句是需要重點分析的:

了解這個表達式作為左值之前,先了解一下*這個操作符。

*這是一個間接通路的操作符。

通過一個指針通路它所指向的位址的過程稱為間接通路(indirection)或解引用指針(dereferencing the pointer)。

是不是有點難以了解?

下面直接給出上面的*p作為左值所表達的意義:*p作為左值代表的是指針變量p所指向的位址。

或者說,指針p的值是記憶體中某個特定位置的位址,*操作符使機器指向那個位置。當它作為左值使用時,這個表達式指定需要進行修改的位置。當它作為右值時,它就是提取目前存儲于這個位置的值。

還不是太明白?那。。。

舉個實際的例子:

//下面是這些變量的聲明
int a = 112, b = -1;
float c = 3.14;
int *d = &a;
float *e = &c;      

d的值是a的位置(&a),假設為100;

當我們對d使用間接通路操作符時,它表示通路記憶體位置100并察看那裡的值。

是以,*d的右值是112;而它的左值表示它指向的那個位置本身,是以是100本身。

我想舉了這個實際的例子,大家已經明白了,左值與右值的含義了,不過還是免不了要憤怒。。。(真jr難了解,真jr麻煩!)哎,隻能用熟能生巧來安慰自己了。

對于指針表達式,我下篇博文專門介紹一些有深度的内容,可謂是撲朔迷離,但是如果想深入掌握這門語言,還是要下功夫去研究。