【问题标题】:Errors using ternary operator in c在 c 中使用三元运算符的错误
【发布时间】:2014-12-14 10:18:44
【问题描述】:

我有一段 C 代码如下:

main()
{
    int a=10, b;
    a>=5 ? b=100 : b=200 ;
    printf("%d" , b);
}

在 unix 的 gcc 编译器上运行代码会生成编译时错误 '需要左值作为赋值的左操作数'并将错误指向 b = 200,而在 Windows 中使用 Turbo C 编译时会给出 200 作为输出。

谁能解释一下在这种情况下到底发生了什么?

【问题讨论】:

标签: c gcc turbo-c


【解决方案1】:

在这种情况下,括号应该围绕条件。

(a>=5) ? b=100 : b=200; 应该可以正确编译

RE: K&R The C Programming Language (2nd):

条件表达式的第一个表达式不需要括号,因为?: 的优先级非常低,刚好高于赋值。 (强调我的)无论如何,它们都是可取的,因为它们使表达式的条件部分更容易看到。

【讨论】:

    【解决方案2】:

    这个错误是由条件表达式的语法引起的

    logical-OR-expression ? expression : conditional-expression
    

    因此:之后的部分必须能够解析b = 200。但是,conditional-expression 无法解析它,因为赋值表达式的优先级较低 - 您需要在赋值表达式周围加上括号

    a>=5 ? b=100 : (b=200);
    

    但您在此处需要括号这一事实确实意味着该表达式否则会被解析为(a>=5 ? b=100 : b) = 200,它只是编译器的内部人工制品,在错误消息中它谈到了左边赋值操作数。 C语言赋值表达式语法有以下两条规则,匹配的规则适用

    conditional_expression
    unary_expression '=' assignment_expression
    

    这会干扰递归下降解析器,它只会调用parseConditionalExpression,并检查后面的标记。因此,一些 C 解析器实现选择在此处不给出语法错误,而是将其解析为好像上面的语法说 conditional_expression '=' ...,然后在检查解析树时,验证左侧是左值。例如,Clang 源代码说

    /// Note: we diverge from the C99 grammar when parsing the assignment-expression
    /// production.  C99 specifies that the LHS of an assignment operator should be
    /// parsed as a unary-expression, but consistency dictates that it be a
    /// conditional-expession.  In practice, the important thing here is that the
    /// LHS of an assignment has to be an l-value, which productions between
    /// unary-expression and conditional-expression don't produce.  Because we want
    /// consistency, we parse the LHS as a conditional-expression, then check for
    /// l-value-ness in semantic analysis stages.
    

    GCC 解析器的源代码说

    /* ...
    In GNU C we accept any conditional expression on the LHS and
    diagnose the invalid lvalue rather than producing a syntax
    error. */
    

    【讨论】:

      【解决方案3】:

      在 C 中,三元运算符的定义如下

      逻辑或表达式?表达式:条件表达式

      条件表达式定义如下

      logical-OR-expression
      

      赋值运算符的优先级低于 OR 运算符。因此你必须写

      a >= 5 ? b = 100 : ( b = 200 );
      

      否则编译器会将表达式视为

      ( a >= 5 ? b = 100 :  b ) = 200;
      

      由于C中的三元运算符不是左值,所以上面的表达式无效,编译器报错。

      来自 C 标准:

      结果是第二个或第三个操作数的 (以 被评估),转换为下面描述的类型

      和脚注:

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

      考虑到 C 和 C++ 中的运算符定义之间存在本质区别。在 C++ 中它被定义为

      逻辑或表达式?表达式:赋值表达式

      在 C++ 中,同样的 GCC 可以成功编译代码

      #include <iostream>
      
      int main() 
      {
          int a = 10, b;
      
          a >= 5 ? b = 100 : b = 200;
      
          std::cout << "b = " << b << std::endl;
      
          return 0;
      }
      

      【讨论】:

      • 这不是那个问题的重复吗?我是不是用这个错误地关闭了?:stackoverflow.com/a/6966331/1275169
      • @Blue Moon 如果我在这些问题中没有弄错的话,则认为运营商的不同部分。所以我认为它们是相互附加的。
      • AFAICS,它解决了完全相同的问题。
      • @Blue Moon 存在同样的问题,只是因为它是三元运算符的问题。但是运营商有三个部分值得单独讨论。
      • 这看起来不正确。 C 中的赋值是“一元表达式操作赋值表达式”。因此,“否则编译器认为表达式 like...”是不正确的。编译器只会将表达式视为语法废话。任何像“需要左值”这样合理的错误消息都只是 QoI。
      【解决方案4】:

      你可以把它放在大括号里让它工作..就像

      (a>=5)?(b=100):(b=200);
      

      请为您的函数分配一个返回类型main()

      【讨论】:

        【解决方案5】:

        试试这个!因为三元运算符返回你必须将其赋值给b的值!

        #include <stdio.h>
        
        main() {
        
            int a = 10, b;
            b = a >= 5 ? 100 : 200;
            printf("%d" , b);
        
        }
        

        【讨论】:

        • 谢谢.. 但我的问题是关于相同代码在两个不同编译器中的不同响应。你能详细说明这一点吗?再次感谢你:)
        • @Rizier123:它不是未定义的。
        猜你喜欢
        • 2020-11-23
        • 2012-06-02
        • 1970-01-01
        • 2012-12-18
        • 2021-10-30
        • 2023-03-05
        • 2014-05-03
        • 2011-05-17
        • 2010-12-13
        相关资源
        最近更新 更多