為什麼這篇c運算子順序鄉民發文收入到精華區:因為在c運算子順序這個討論話題中,有許多相關的文章在討論,這篇最有參考價值!作者purpose (purpose)看板C_and_CPP標題Re: [問題] 新手運算子的優先問...
※ 引述《william6718 (有錢沒錢當個阿宅好過年)》之銘言:
: 開發平台(Platform): (Ex: VC++, GCC, Linux, ...)
: Dev C++5.0
: 問題(Question):
: 小弟最近在學習指針的時候發生了運算子優先級的困擾...
: 程式碼如下
: #include <stdio.h>
: #include <windows.h>
: int main(void)
: {
: int ar[6]={1,2,3,4,5,0};
: int *ptr=ar;
: *ptr++;
: printf("%d\n",*p);
: printf("%p\n",p);
: system("pause");
: }
: 疑惑出現*ptr++;這一段
: 我查書上有書說:
: 指針ptr先取值再自加的動作
: 不過也有書說
: 指針ptr先自加再取值的動作
: 神奇的是...
: 我查運算優先級資料
: 有後綴++優先於*的說法
: 也有後綴++與*同級的說法
: 還是這個問題是要看編譯器來決定?
: 煩請各位高手指點迷津
: 剛剛試了一下
: *ptr++ 結果是2 記憶體是0022FEF8
: *++ptr 結果是2 記憶體是0022FEF8
: 結果是一樣的
: 所以要如何解釋這兩個運作...越來越糊塗了
重新回文講比較清楚一點,順便做個運算子觀念小整理。
運算子優先權先後的判斷
觀念上,小括號的優先權最高,然後是 C++ 新增的 :: 運算子次之,
接著是 postfix 系列的運算子。接著才輪到 prefix 系列。
另外就是一元運算子幾乎都優先於二元運算子,這也很容易理解。
小括號,可以當成 "一體化" 運算,也就是說括號裡面不管有多少內容都要先自己合體,
才能跟小括號相鄰的左或右去做交流。
比如:(obj + 1) * (obj + 2)
做相乘前,要先算出左右兩邊的值,而因為有小括號存在,所以得先做
obj + 1 與 obj + 2 這兩個運算,但先做哪個相加沒有硬性規定。
至於 postfix 的優先權比較高,這不妨背一下,
比如 codeproject 有一篇:How to interpret complex C/C++ declarations
他的大意是說,要解讀宣告時,
第一步是找到識別項的位置,然後先往右看再往左看,其原理就是基於
postfix 運算子的優先權,永遠高於 prefix 運算子,所以才先往右看。
所以如果你的書寫「後綴++與*同級的說法」那就錯了,因為
* 當 dereference 取值運算時,是 prefix 形態,不可能跟 postfix 同級。
所謂 side effect 與 sequence point
如果要查順序點有哪些,可以參考:
http://en.wikipedia.org/wiki/Sequence_point
最有名的副作用就是 postfix ++ 了,這一定要知道的。
ptr++ 這個運算中,優先權最高的運算是 postfix ++
此運算子的主要目的是 evaluate (運算出) 其運算元的值為何,然後
會有一個副作用 (side effect) 會改變此運算元的內容,將其做遞增運算。
由此可知,這個運算子的運算元不能是 const 只能是 non-const,才能被副作用。
副作用就像吃藥一樣,你為了治療感冒,卻得到頭暈的副作用。
其中的頭暈不是你吃這個藥追求的東西。
同理可知,這裡讓運算元遞增也不是該運算的主要目的。
所謂的順序點就是保證在此點之前的所有副作用,都會在此順序點之後全部生效完畢。
回到 *ptr++; 例子:
在這個例子中的 ++ 其運算元就只是 ptr 這個變數,而不是任何運算式 (expression),
所以運算的結果,就是把 ptr 的值原封不動讀取出來。
假設是讀取出 0x1234 好了,接著的副作用是將「原運算元 ptr」的內容做遞增,
也就是讓 ptr 儲存的值變成 0x1238,但這個副作用何時生效還不知道,要等到
出現順序點才能確保,因此繼續做第二個運算,也就是取值運算。
在取值運算 * 中,會使用前次運算的運算結果,也就是 0x1234 來取值,
而不是針對 ptr 變數來取值,所以雖然順序點還沒出現,也不影響取值的結果,還是
能得到 0x1234 記憶體位址所儲存的內容。
而最後的分號,代表結束此次運算,代表是一個完整的 statement,每個 statement
之間,都有順序點,因此 *ptr++; 的下一個 statement 時,必然保證
指標變數 ptr 的內容值已經被遞增為 0x1238。
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 124.8.130.31