首先需要知道三點,在C語言中:
函式引數的求值順序是
未指定
的(注意,這裡和呼叫規定無關)。
如果一個標量物件上的副作用和一個需要用到同一個標量物件的值之間的順序是不確定的,那麼行為
未定義
。
逗號運算子(注意,這和函式引數列表中的逗號不同)保證從左到右運算。
那麼結果就很清楚了:不加括號時,函式引數的求值順序是未指定的,這導致了 x = 2 中對x的賦值和 y = x + 3 / 2 中對x的使用之間的順序是不確定的,這是未定義行為。而加了括號的時候,就會保證先 x = 2,再 y = x + 3 / 2,得到 3 並輸出。
我覺得應該是printf裡面只有一個%f,所以自動對齊到第一個引數也就是a,所以只是輸出了a的值,y的值計算了,但是在格式化輸出裡面沒有說要輸出。
就像下面這程式碼是正確的
printf(“%d”,a,b,c,d)
只會輸出a,因為格式化輸出裡面只有一個,所以自動對齊到a,至於後面的三個引數,是會進行運算的,但是結果不會輸出。這是printf裡面的逗號規則。
而加了括號的才是逗號運算子
printf(“%d”,(a,b))
也就是返回右邊語句的值。另外,x=2是會返回一個值的副本的。所以x=2這個表示式的值是2。
建議谷歌:序列點,未定義行為。
吐個槽 答案在warning裡
這個問題要正確理解函式的處理順序就迎刃而解了。函式的處理順序為:
1、printf是一個可變引數的輸入函式。
2、編譯器會先計算每一個形參表示式。計算的順序是,先處理尾部的引數表示式,並把表示式結果引數的地址壓棧。所以,在這一步先計算y的結果會計算結束,為11。
3、跳轉到函式的處理地址。
4、printf函式從堆疊中取出每一個引數。
5、按照格式化字串輸出x的數值。
6、函式退出,出棧,回到函式呼叫的下一行。
關於加括號後,處理思路一樣,在括號表示式中,括號部分作為一個引數,先處理括號內部的表示式,該表示式是我們理解的順序處理,先處理x=2,在處理y=x+3/2,並把y作為括號內部的表示式處理結果,壓棧y的地址給printf。