【问题标题】:Conditional operator differences between C and C++C 和 C++ 之间的条件运算符区别
【发布时间】:2010-11-08 03:12:28
【问题描述】:

我在某处读到 C 中的 ?: 运算符在 C++ 中略有不同,有一些源代码在两种语言中的工作方式不同。不幸的是,我在任何地方都找不到文本。有谁知道这个区别是什么?

【问题讨论】:

    标签: c++ c conditional-operator


    【解决方案1】:

    C++ 中的条件运算符可以返回左值,而 C 不允许类似的功能。因此,以下在 C++ 中是合法的:

    (true ? a : b) = 1;
    

    要在 C 中复制它,您将不得不求助于 if/else,或者直接处理引用:

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

    同样在 C++ 中,?:= 运算符有 equal precedence and group right-to-left,这样:

    (true ? a = 1 : b = 2);
    

    是有效的 C++ 代码,但会在最后一个表达式周围不带括号的情况下在 C 中引发错误:

    (true ? a = 1 : (b = 2));
    

    【讨论】:

    • 在 C 中你可以写成 *(true? &a: &b) = 1
    • 只是一个关于(condition ? a = 1 : b = 2); 的小问题——这是否用作 if-else 情况的“快捷方式”?你认为这经常发生吗?我倾向于认为它被滥用:-/
    • =?: 操作符的最后部分在 C 语法中没有定义,但是许多编译器将其解析为 "a ? b = 1 : c = 1" == "(a ? (b = 1) : c) = 1",然后会失败,因为 ?: 从来都不是C中的左值。见en.cppreference.com/w/c/language/operator_precedence
    【解决方案2】:

    主要的实际区别在于,在 C 中,评估 ?: 永远不会产生左值,而在 C++ 中却可以。

    它的定义还有其他一些差异,几乎没有实际影响。在 C++ 中,第一个操作数被转换为布尔值,在 C 中它与 0 进行比较。这类似于 C 和 C++ 之间 ==、!= 等定义的差异。

    C++ 中还有更复杂的规则来推导 ?: 表达式的类型,它基于第二个和第三个操作数的类型。这反映了 C++ 中用户定义的隐式转换的可能性。

    示例代码。有效的 C++;无效的C。

    extern int h(int p, int q);
    
    int g(int x)
    {
            int a = 3, b = 5;
    
            (x ? a : b) = 7;
    
            return h( a, b );
    }
    

    gcc编译为C时产生错误:“error: invalid lvalue in assignment”,但编译为C++时代码编译没有错误。

    编辑: 虽然 ?: 不能在 C 中返回左值,但令人惊讶的是 ?: 的语法是:

    conditional-expression:
        logical-OR-expression
        logical-OR-expression ? expression : conditional-expression
    

    这意味着a ? b : c = d 解析为(a ? b : c) = d,即使(由于“非左值”规则)这不会导致有效的表达式。

    C++ 将语法改为:

    conditional-expression:
        logical-or-expression
        logical-or-expression ? expression : assignment-expression
    

    虽然在某些情况下允许条件表达式为左值的扩展会使 a ? b : c = d 在不更改语法的情况下有效,但新的语法更改意味着表达式现在有效但具有不同的 @ 含义987654328@.

    虽然我没有任何证据,但我的假设是,由于语法更改不会破坏与现有 C 代码的兼容性,因此新语法更有可能对以下表达式产生更少的意外:

    make_zero ? z = 0 : z = 1;
    

    【讨论】:

    • 描述 C 解析的部分答案不正确。在 C 语法中,= 运算符的 LHS 不能包含非括号 ?: 运算符。建议的 (a ? b : c) = d 解析实际上是不可能的。在 C 语法中,a ? b : c = d 表达式根本不可解析。任何将其解释为(a ? b : c) = d 的编译器都需要自担风险。 (这通常是在混合 C/C++ 编译器中尝试统一 C 和 C++ 语法的情况。)形式上,它没有问题,因为仍然拒绝无效代码。但“不是左值”消息具有误导性。
    • 在 C 中,a ? b : c = d 只是句法上的乱码,一个不可解析的标记序列。它不是一种表达方式。声称它分配给非左值是不正确的,因为这里没有“分配”。
    猜你喜欢
    • 1970-01-01
    • 2013-04-29
    • 2016-05-15
    • 1970-01-01
    • 2015-07-16
    • 2013-11-02
    • 2017-05-05
    • 2019-08-26
    相关资源
    最近更新 更多