2016年11月14日 星期一

[C/C++] Prefix/Postfix Increment/Decrement Operators

Prefix/Postfix Increment/Decrement Operators


今天在研究 Sequence Point 的時候發現一個有趣的 expression:

int i = 0, j;
j = ++++++i;

這邊就不探討 sequence point 的問題了,直接來說關於這行 ++++++i 是什麼鬼東西。

R-value 跟 L-value


首先要知道關於 rvalue 跟 lvalue,而他們最簡單且籠統的定義就是:

  • rvalue: = 右邊的東西
  • lvalue: = 左邊的東西

進一步來說,lvalue 就是只你可以『給值』的東西,是有實體記憶體的,例如說一般變數:

int x;

,所以你可以給值:

x = 3;

,那 rvalue 呢?一般來說是不是 lvalue 的都叫做 rvalue。


這也太籠統了吧?!舉個例子來看看:

3

似乎很有道理,因為你應該不會寫出像這樣的 code:

3 = x;

吧?因為 3 不能給值,所以我們把他歸類為 rvalue。


當然 rvalue 跟 lvalue 並不是像我這種憨人所想得這麼簡單,否則網路上也不會這麼多文章再探討 rvalue 跟 lvalue 了,但畢竟這不是這篇文章要講的重點,所以就不詳細說明了。

++++++i;


回到這鬼玩意兒,聰明的你可能知道他應該是長這個樣子:

++ ++ ++i;

你可以再更靠近一點:


++  ++  ++i;


看不出來的話我們在更進一步表示一下:


++ ( ++ ( ++i ) );


對 C 跟 C++ 來說這鬼玩意兒就是這樣解釋的。


看懂之後那問題來了,這行 code 是正確的嗎?


首先講一下 C++,對 C++ 來說,
  • Prefix Operator (++x): 回傳的是 lvalue
  • Postfix Operator (x++): 回傳的是 rvalue

Prefix versions of the built-in operators return references and postfix versions return values. [1]

既然 ++x 是回傳 lvalue 代表我們可以繼續修改他回傳的記憶體,所以那個鬼玩意兒對 C++ 來說最後 i 的結果就是 3。


那對 C 來說呢?很抱歉,兩個都不是回傳 lvalue。


這也意味著在最裡面那個括號做完以後是不能修改的,當然就不能在對他做 ++ 囉,所以 C 的編譯器在編譯的時候就會報錯:


test.c: In function ‘main’:
test.c:3:7: error: lvalue required as increment operand
     ++++++i;
       ^


結論



又是一個搞死人的 code。


Reference

  1. http://en.cppreference.com/w/cpp/language/operator_incdec
  2. https://stackoverflow.com/questions/21351799/postfix-prefix-increment-l-value-and-r-value-in-c-and-c


沒有留言:

張貼留言