C 和 C++ 之间的条件运算符区别

Posted

技术标签:

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

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

【问题讨论】:

【参考方案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 只是句法上的乱码,一个不可解析的标记序列。它不是一种表达方式。声称它分配给非左值是不正确的,因为这里没有“分配”。

以上是关于C 和 C++ 之间的条件运算符区别的主要内容,如果未能解决你的问题,请参考以下文章

具有范围解析和条件的 C++ 三元运算符

C++ 条件运算符

带有 void 操作数的 C++ 条件运算符

在c或c ++中通过结构对象变量创建树的点运算符和箭头运算符之间的区别[重复]

C++ - (*) 之间的区别。和->?

C++:TrivialStandard-Layout 和 POD