条件运算符的结果是左值还是右值?
Is the result of the conditional operator an lvalue or rvalue?
我们知道条件运算符 returns 如果它的 Expr2
和 Expr3
是相同类型的左值,则它是一个左值,否则它 returns 是一个右值:
int main(){
int a = 0, b = 0;
(a == 1 ? a : b) = 1; // C++ OK. C: error. lvalue needed
return 0;
}
- 上面的代码在 C++ 上编译罚款,但在 C 上编译失败。
这是 C:
上的输出
main.c: In function ‘main’:
main.c:8:20: error: lvalue required as left operand of assignment
(a == 1 ? a : b) = 1;
^
在C中,条件运算符的结果1是一个右值(C标准术语中的“值”),因为C 2018 6.3.2.1 2说:
Except when it is the operand of the sizeof
operator, the unary &
operator, the ++
operator, the --
operator, or the left operand of the .
operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue);…
因此,虽然条件运算符的结果是它的第二个或第三个操作数,但该操作数已转换为一个值,不再是左值。
如 M.M 所述,您可以通过选择操作数的地址然后应用 *
:
来获得与选择左值相同的效果
*(a == 1 ? &a : &b) = 1;
脚注
1 条件运算符的结果不是 return 值,因为不涉及函数调用,所以不存在 call-and-return, 只是一个表达式求值。
这是 C++ 和 C 不同的情况之一。在 C 中,条件运算符产生右值,因此它不能位于赋值的左侧。
表达式1?表达式 2 : 表达式 3
如果表达式 1 具有真(非零)值,则整个条件表达式采用与表达式 2 相同的值。如果表达式 1 具有假(空)值,则整个条件表达式将获得与表达式 3 相同的值。
P r i m e r s
(5 > 3) ? 1 : 2 gets the value 1.
(3 > 5) ? 1 ; 2 gets the value 2.
(a > b) ? a : b gets a larger value among a or b.
The conditional operation itself is not a function that
returns a value.
在this C11 Draft Standard中有一个脚注明确指出条件运算符的结果不是左值:
6.5.15 Conditional operator
…
Semantics
4 The first operand is evaluated; there is a sequence point between its evaluation and the evaluation of
the second or third operand (whichever is evaluated). 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.110)
110) A conditional expression does not yield an lvalue.
此外,in this later draft Standard(日期为 2019 年 3 月),措辞没有显着变化(除了其中的脚注编号为 116,而不是 110)。
我们知道条件运算符 returns 如果它的 Expr2
和 Expr3
是相同类型的左值,则它是一个左值,否则它 returns 是一个右值:
int main(){
int a = 0, b = 0;
(a == 1 ? a : b) = 1; // C++ OK. C: error. lvalue needed
return 0;
}
- 上面的代码在 C++ 上编译罚款,但在 C 上编译失败。
这是 C:
上的输出main.c: In function ‘main’:
main.c:8:20: error: lvalue required as left operand of assignment
(a == 1 ? a : b) = 1;
^
在C中,条件运算符的结果1是一个右值(C标准术语中的“值”),因为C 2018 6.3.2.1 2说:
Except when it is the operand of the
sizeof
operator, theunary &
operator, the++
operator, the--
operator, or the left operand of the.
operator or an assignment operator, an lvalue that does not have array type is converted to the value stored in the designated object (and is no longer an lvalue);…
因此,虽然条件运算符的结果是它的第二个或第三个操作数,但该操作数已转换为一个值,不再是左值。
如 M.M 所述,您可以通过选择操作数的地址然后应用 *
:
*(a == 1 ? &a : &b) = 1;
脚注
1 条件运算符的结果不是 return 值,因为不涉及函数调用,所以不存在 call-and-return, 只是一个表达式求值。
这是 C++ 和 C 不同的情况之一。在 C 中,条件运算符产生右值,因此它不能位于赋值的左侧。
表达式1?表达式 2 : 表达式 3 如果表达式 1 具有真(非零)值,则整个条件表达式采用与表达式 2 相同的值。如果表达式 1 具有假(空)值,则整个条件表达式将获得与表达式 3 相同的值。
P r i m e r s
(5 > 3) ? 1 : 2 gets the value 1.
(3 > 5) ? 1 ; 2 gets the value 2.
(a > b) ? a : b gets a larger value among a or b.
The conditional operation itself is not a function that
returns a value.
在this C11 Draft Standard中有一个脚注明确指出条件运算符的结果不是左值:
6.5.15 Conditional operator
…
Semantics
4 The first operand is evaluated; there is a sequence point between its evaluation and the evaluation of the second or third operand (whichever is evaluated). 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.110)
110) A conditional expression does not yield an lvalue.
此外,in this later draft Standard(日期为 2019 年 3 月),措辞没有显着变化(除了其中的脚注编号为 116,而不是 110)。