yohhoyの日記

技術的メモをしていきたい日記

条件演算子と左辺値の扱いの差

プログラミング言語C/C++における条件演算子(?:)と左辺値の扱いについてメモ。言語仕様の隅をつつく話題であり、通常はif文を利用するべき。

下記コードはCでは未定義動作(undefined behavior)を引き起こすが、C++ではwell-definedであり期待通り動作する(変数aに値42を代入)。

int a = 0, b = 0, c = 1;
(c ? a : b) = 42;

次のようにポインタ経由とすれば、C/C++両方で意図通り動作する。

 *(c ? &a : &b) = 42;

C

C99(JTC1/SC22/WG14 N1256) 6.5.15/p4より引用。C11(WG14 N1570)でも同一。

4 The first operand is evaluated; there is a sequence point after its evaluation. The second operand is evaluated only if the first compares unequal to 0; the third operand is evaluated only if the first compares equal to 0; the result is the value of the second or third operand (whichever is evaluated), converted to the type described below.95) If an attempt is made to modify the result of a conditional operator or to access it after the next sequence point, the behavior is undefined.
脚注95) A conditional expression does not yield an lvalue.

C++

C++03 5.16/p4より引用。

If the second and third operands are lvalues and have the same type, the result is of that type and is an lvalue.

C++11(JTC1/SC22/WG21 N3337) 5.16/p4より引用。

If the second and third operands are glvalues of the same value category and have the same type, the result is of that type and value category and it is a bit-field if the second or the third operand is a bit-field, or if both are bit-fields.

C.1 CompatibilityにCとC++の差分が明記されている。一部引用。

Change: The result of a conditional expression, an assignment expression, or a comma expression may be an lvalue
Rationale: C++ is an object-oriented language, placing relatively more emphasis on lvalues. For example, functions may return lvalues.
Effect on original feature: Change to semantics of well-defined feature. Some C expressions that implicitly rely on lvalue-to-rvalue conversions will yield different results.

関連URL