【问题标题】:Is the result of the conditional operator an lvalue or rvalue?条件运算符的结果是左值还是右值?
【发布时间】:2021-09-26 16:07:18
【问题描述】:

我们知道条件运算符返回一个左值,如果它的Expr2Expr3 是相同类型的左值,否则它返回一个右值:

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 中,条件运算符总是产生一个右值,而不是一个左值。标准中似乎没有明确说明,但确实会产生左值的运算符被特别提及,?: 没有。
  • “我们知道”后跟虚假陈述
  • 如果两个操作数都是左值,你可以通过*(a==1 ? &a : &b)得到一个左值结果

标签: c conditional-operator


【解决方案1】:

在 C 中,条件运算符的结果1 是一个右值(C 标准术语中的“值”),因为 C 2018 6.3.2.1 2 说:

除非它是 sizeof 运算符、unary & 运算符、++ 运算符、-- 运算符或 . 运算符或赋值运算符的左操作数,否则不具有数组类型的左值转换为存储在指定对象中的值(不再是左值);…

因此,虽然条件运算符的结果是它的第二个或第三个操作数,但该操作数已被转换为一个值,不再是左值。

正如M.M 所说,您可以通过选择操作数的地址然后应用* 来获得与选择左值相同的效果:

*(a == 1 ? &a : &b) = 1;

脚注

1条件运算符的结果不是返回值,因为不涉及函数调用,所以没有call-and-return,只是表达式求值。

【讨论】:

    【解决方案2】:

    this C11 Draft Standard 中,有一个脚注清楚地表明条件运算符的结果不是左值:

    6.5.15 条件运算符


    语义

    4    评估第一个操作数;在其评估和评估之间有一个序列点 第二个或第三个操作数(以被评估者为准)。第二 仅当第一个比较不等于 0 时才计算操作数;这 仅当第一个比较等于 0 时才评估第三个操作数;这 结果是第二个或第三个操作数的值(以 评估),转换为下面描述的类型。110)


    110) 条件表达式不会产生左值。

    此外,in this later draft Standard(日期为 2019 年 3 月),措辞没有显着变化(除了脚注编号为 116,而不是 110)。

    【讨论】:

      【解决方案3】:

      这是 C++ 和 C 不同的情况之一。在 C 中,条件运算符产生一个右值,因此它不能是赋值的左侧。

      【讨论】:

        【解决方案4】:

        表达式1?表达式2:表达式3 如果表达式 1 具有真(非零)值,则整个条件表达式采用与表达式 2 相同的值。如果表达式 1 的值为假(null),则整个条件表达式的值与表达式 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.
        

        【讨论】:

        • 问题不在于条件运算符产生什么value。问题是关于值的type,特别是它是否是可以在赋值运算符左侧使用的lvalue
        • 在我看来,从我所写的内容来看,这个问题的答案变得显而易见。如果不是这样,那我就错了。
        猜你喜欢
        • 2014-11-20
        • 2014-03-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多