Re: [問題] 新手運算子的優先問題

看板C_and_CPP作者 (purpose)時間12年前 (2012/04/17 23:50), 編輯推噓3(300)
留言3則, 3人參與, 最新討論串2/2 (看更多)
※ 引述《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

04/17 23:57, , 1F
感謝高手的指點!! 我有種恍然大悟的感覺 謝謝您
04/17 23:57, 1F

04/18 00:14, , 2F
好文!
04/18 00:14, 2F

04/20 18:33, , 3F
推!
04/20 18:33, 3F
文章代碼(AID): #1FZP5JaR (C_and_CPP)
文章代碼(AID): #1FZP5JaR (C_and_CPP)