C ++中逗号运算符的不同行为与返回?

Posted

技术标签:

【中文标题】C ++中逗号运算符的不同行为与返回?【英文标题】:Different behaviour of comma operator in C++ with return? 【发布时间】:2017-01-14 19:29:09 【问题描述】:

这个(注意逗号操作符):

#include <iostream>
int main() 
    int x;
    x = 2, 3;
    std::cout << x << "\n";
    return 0;

输出 2

但是,如果您将return 与逗号运算符一起使用,则:

#include <iostream>
int f()  return 2, 3; 
int main() 
    int x;
    x = f();
    std::cout << x << "\n";
    return 0;

输出 3

为什么逗号运算符与return 的行为不同?

【问题讨论】:

en.wikipedia.org/wiki/Comma_operator 【参考方案1】:

根据Operator Precedence,comma operator的优先级低于operator=,所以x = 2,3;等价于(x = 2),3;。 (运算符优先级决定了运算符如何绑定到它的参数,根据它们的优先级比其他运算符更紧或更松。)

注意这里的逗号表达式是(x = 2),3,而不是2,3x = 2 首先被评估(并且它的副作用已经完成),然后结果被丢弃,然后3 被评估(它实际上什么都不做)。这就是x 的值是2 的原因。请注意3 是整个逗号表达式的结果(即x = 2,3),它不会用于分配给x。 (改成x = (2,3);x会被赋值为3。)

对于return 2,3;,逗号表达式为2,3,计算2,然后丢弃其结果,然后计算3并作为整个逗号表达式的结果返回,由return statement 稍后。


有关Expressions 和Statements 的其他信息

表达式是一系列运算符及其操作数,用于指定计算。

x = 2,3;是expression statement,x = 2,3是这里的表达式。

后跟分号的表达式是语句。

语法:attr(optional) expression(optional) ; (1)

return 2,3; 是jump statement (return statement),2,3 是这里的表达式。

语法:attr(optional) return expression(optional) ; (1)

【讨论】:

很好的解释。但是有一些实际的应用吗?还是只是要完成的错误? @Jean-FrançoisFabre IMO 这只是令人困惑,根本没用。 我曾在 for 循环中看到过一两次使用它,奇怪的是,它可以使代码在数值计算中更清晰 @Jean-FrançoisFabre:就像 Bathesheba 所说的那样,您可以在 for 循环中编写类似 i += 1, j += 2 的内容。有人认为 C++ 语法(或者更确切地说是 C 语法,因为这部分是从那里复制的)已经足够复杂,而没有尝试定义逗号的优先级在您编写 x = 2, 3 时高于赋值,但在您编写 @ 时较低987654357@! @Holger:分号终止语句,它不是运算符。可以对答案进行调整以使其更清楚。 "x = 2 , 3" 是一个有 2 个运算符的表达式,为了支持 for(;;),= 具有更高的优先级。 (正如其他人所说。)但是“return 2, 3;”是包含表达式“2, 3”的语句。 技术上没有优先于关键字“return”的优先级。 (虽然实际上,因为它是接受表达式的语句的一部分,所以它最后被解析——比表达式中的任何运算符in的“优先级”更低。)【参考方案2】:

逗号(也称为表达式分隔)运算符从左到右计算。所以return 2,3; 等价于return 3;

x = 2,3; 的评估是(x = 2), 3;,因为运算符优先级。评估仍然是从左到右,整个表达式的值为3,而x的副作用假设值为2。

【讨论】:

您能否编辑并详细说明表达式分离运算符?就像我在@songyuanyao 的回答的评论中提到的那样,我可以理解为什么return 2,3return (2,3) 是一样的。我认为前者应该是(return 2),3 @BiagioFesta 很好地解释了这部分。 @prakharsingh95 return 2 是一个语句(例如由for,while,if 组成的语句),而不是表达式。你不能写例如f(return 2)2+return 2。所以,(return 2),3 在语法上是无效的。 @chi 是的,你是对的。我的意思是我希望 return 2, 3解释(return 2), 3 @prakharsingh95 根据C++的语法,return只能出现在以下情况:(a)returnexpression_opt;,和(b) return braced-init-list ; .【参考方案3】:

此声明:

  x = 2,3;

由两个表达式组成

> x = 2
> 3

自从operator precedence, = 的优先级高于逗号,,因此x = 2 被评估并且 3 之后。那么x 将等于2


改为return

int f() return 2,3; 

语言语法是:

return <expression>

注意return 不是表达式的一部分。

所以在这种情况下,两个表达式将被评估为:

> 2
> 3

但只会返回第二个 (3)。

【讨论】:

UV'd。非常挑剔,但如果您将&lt;expression&gt; 标记为明确可选(从语法角度来看)会很好。 x=2,3的解析树中有5个表达式。文字 23 都位于解析树的底部,标识符 x 也是如此。这些都是单独有效的表达式。运算符优先级意味着=在解析树中出现lower,并将x2这两个表达式组合成第四个表达式x=2。最后,第五个表达式由逗号运算符连接其两侧x=23 形成。但是,您错误地指出运算符优先级决定了评估的 order。它没有。评估顺序由排序规则决定。 我投票赞成提到 return 不是表达式的一部分 @MSalters 我同意你的观点,但我只是错误地使用了“因为”这个词,而不是“因为”。我的英语不是那么完美! ;-= 这里的“宏观表达”是一个技术术语吗?当预处理器意义上的“宏表达式”也存在时,使用它似乎有点混乱。【参考方案4】:

尝试应用简单的方法,只用括号突出优先级:

( x = 2 ), 3;

return ( 2, 3 );

现在我们可以看到二元运算符“,”在两者上的工作方式相同,从左到右。

【讨论】:

棘手的部分是意识到x = 2, 3 本身就是一个表达式,而对于return 它是return &lt;expression&gt;。所以你把它们读成(x = 2, 3)(2, 3)

以上是关于C ++中逗号运算符的不同行为与返回?的主要内容,如果未能解决你的问题,请参考以下文章

逗号表达式的分析

C函数中逗号分隔的返回参数[重复]

C语言 逗号表达式

将负双精度转换为无符号整数的行为是不是在 C 标准中定义? ARM 与 x86 上的不同行为

python自增自减?赋值语句返回值?逗号表达式?

如何在逗号分隔的字符串行中找到不同的元素?