contributed by <team6612
> (Daniel Chen)
在 C 程式中,表達式 1 << 2 + 3 << 4
求值後為何?
(a)
512
(b)
16
(c)
26
(d)
52
(e)
25
延伸問題:
在 C11 (ISO/IEC 9899:2011) 規格書中,有關運算子的優先順序定義在 6.5 Expressions
一章中,一連串的運算元和運算子組合起來稱爲 Expression,可用來表達:求值、指派、產生 side effect
、或以上的組合。
在規格書中定義優先順序的方式不是列出個列表標示每個運算子的順序,而是一連串的語法定義,來告訴編譯器實作應該要先處理哪種運算子,一共分成 17 種 Expressions,分別是:
各 Expression 的定義可能由別種 Expression 所表達,表示別種 Expression 必須先組合起來再解讀該 Expression,例如 unary-expression
的定義
unary-expression:
postfix-expression
++ unary-expression
-- unary-expression
unary-operator cast-expression
sizeof unary-expression
sizeof ( type-name )
_Alignof ( type-name )
unary-operator: one of
& * + - ~ !
中包含 postfix-expression
及 cast-expression
,意味着當 Expression 中包含這兩種 Expression 時必須先解讀postfix-expression
& cast-expression
再解讀 unary-expression
。
C Operator Precedence - cppreference.com 將這樣的關係整理成 precedence table,但也有提到不是所有的語法定義都可以很好的用次序表定義,例如三元運算子。
side-effect
的順序在 6.5
中第二點提到
If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings.
並舉了兩個例子
a[i++] = i; //! undefined
a[i] = i; // allowed
i = ++i + 1; //! undefined
i = i + 1; // allowed
第一次看的時候不太懂,於是去找了一些資料來看,其中在 StackOverflow 上找到的這篇和這篇有討論到這個規範的解讀,目前還在研究當中。
string-literal
是 primary-expression
的一種,用來表示字串,規格書在敘述中有提到 string-literal
是 lvalue
,宣告時就佔有記憶體空間,可以對其做相關操作,之前並無注意到此特性,因此做了一點小實驗,對 string-literal
進行 address-of (&)
操作:
printf("&\"string-literal\" = %p\n", &"string-literal");
執行結果
&"string-literal" = 0x561204b247de