当前位置:  开发笔记 > 编程语言 > 正文

逗号运算符如何工作

如何解决《逗号运算符如何工作》经验,为你挑选了6个好方法。

逗号运算符如何在C++中工作?

例如,如果我这样做:

a = b, c;  

最终是否等于b或c?

(是的,我知道这很容易测试 - 只是在这里记录,以便有人快速找到答案.)

更新: 此问题在使用逗号运算符时暴露了细微差别.只是记录下来:

a = b, c;    // a is set to the value of b!

a = (b, c);  // a is set to the value of c!

这个问题实际上是受到代码中的拼写错误的启发.打算做什么

a = b;
c = d;

转换成

a = b,    //  <-  Note comma typo!
c = d;

Konrad Rudol.. 127

请注意,逗号运算符可能在C++中过载.因此,实际行为可能与预期的行为非常不同.

例如,Boost.Spirit非常巧妙地使用逗号运算符来实现符号表的列表初始值设定项.因此,它使以下语法成为可能且有意义:

keywords = "and", "or", "not", "xor";

请注意,由于运算符优先级,代码(故意!)相同

(((keywords = "and"), "or"), "not"), "xor";

也就是说,第一个被调用的运算符是keywords.operator =("and")返回一个代理对象,在该代理对象上operator,调用其余的s:

keywords.operator =("and").operator ,("or").operator ,("not").operator ,("xor");

@Jeff恰恰相反.在列表周围有一个括号,这不起作用,因为编译器只看到两个`char []`之间的逗号运算符,它不能重载.代码*故意*先为每个剩余元素调用`operator =`然后调用`operator,`. (17认同)


efotinis.. 122

逗号运算符具有所有C/C++运算符的最低优先级.因此,它始终是绑定到表达式的最后一个,这意味着:

a = b, c;

相当于:

(a = b), c;

另一个有趣的事实是逗号运算符引入了一个序列点.这意味着表达式:

a+b, c(), d

保证按顺序评估其三个子表达式(a + b,c()d).如果它们有副作用,这是很重要的.通常,编译器可以按照他们认为合适的顺序评估子表达式; 例如,在函数调用中:

someFunc(arg1, arg2, arg3)

可以按任意顺序评估参数.请注意,函数调用中的逗号不是运算符; 他们是分隔符.



1> Konrad Rudol..:

请注意,逗号运算符可能在C++中过载.因此,实际行为可能与预期的行为非常不同.

例如,Boost.Spirit非常巧妙地使用逗号运算符来实现符号表的列表初始值设定项.因此,它使以下语法成为可能且有意义:

keywords = "and", "or", "not", "xor";

请注意,由于运算符优先级,代码(故意!)相同

(((keywords = "and"), "or"), "not"), "xor";

也就是说,第一个被调用的运算符是keywords.operator =("and")返回一个代理对象,在该代理对象上operator,调用其余的s:

keywords.operator =("and").operator ,("or").operator ,("not").operator ,("xor");


@Jeff恰恰相反.在列表周围有一个括号,这不起作用,因为编译器只看到两个`char []`之间的逗号运算符,它不能重载.代码*故意*先为每个剩余元素调用`operator =`然后调用`operator,`.

2> efotinis..:

逗号运算符具有所有C/C++运算符的最低优先级.因此,它始终是绑定到表达式的最后一个,这意味着:

a = b, c;

相当于:

(a = b), c;

另一个有趣的事实是逗号运算符引入了一个序列点.这意味着表达式:

a+b, c(), d

保证按顺序评估其三个子表达式(a + b,c()d).如果它们有副作用,这是很重要的.通常,编译器可以按照他们认为合适的顺序评估子表达式; 例如,在函数调用中:

someFunc(arg1, arg2, arg3)

可以按任意顺序评估参数.请注意,函数调用中的逗号不是运算符; 他们是分隔符.


值得指出的是,``具有如此低的优先级,它甚至落后于_itself_;)......即:comma-as-_operator_的优先级低于逗号为_separator_.因此,如果要在单个函数参数,变量赋值或其他逗号_separated_列表中使用comma-as-_operator_,则需要使用括号,例如:`int a = 1,b = 2,weirdVariable =( ++ a,b),d = 4;`

3> Leon Timmerm..:

它等于b.

逗号运算符的优先级低于赋值.



4> CygnusX1..:

逗号运算符:

优先级最低

是左联想的

为所有类型(内置和自定义)定义了默认版本的逗号运算符,它的工作方式如下 - 给定exprA , exprB:

exprA 被评估

结果exprA被忽略了

exprB 被评估

的结果exprB被返回作为整个表达式的结果

对于大多数运算符,允许编译器选择执行顺序,如果它不影响最终结果,甚至需要跳过执行(例如,false && foo()将跳过调用foo).然而,这不是逗号运算符的情况,并且上述步骤将始终发生*.

实际上,默认的逗号运算符的工作方式与分号几乎相同.不同之处在于,由分号分隔的两个表达式形成两个单独的语句,而逗号分隔将所有表达式保留为单个表达式.这就是为什么逗号运算符有时用于以下场景:

C语法需要单个表达式,而不是语句.例如inif( HERE )

C语法需要单个语句,而不是更多,例如在for循环的初始化中for ( HERE ; ; )

当你想跳过花括号并保持一个声明:( if (foo) HERE ;请不要这样做,它真的很丑!)

如果语句不是表达式,则分号不能用逗号替换.例如,这些是不允许的:

(foo, if (foo) bar)(if不是表达)

int x,int y(变量声明不是表达式)


在您的情况下,我们有:

a=b, c;,相当于a=b; c;,假设该a类型不会使逗号运算符超载.

a = b, c = d;相当于a=b; c=d;,假设该a类型不会使逗号运算符重载.


请注意,并非每个逗号实际上都是逗号运算符.一些逗号含义完全不同:

int a, b; ---变量声明列表以逗号分隔,但这些不是逗号运算符

int a=5, b=3; ---这也是一个逗号分隔的变量声明列表

foo(x,y)---以逗号分隔的参数列表.事实上,x并且y可以在被评估的任何命令!

FOO(x,y) ---逗号分隔的宏参数列表

foo ---逗号分隔的模板参数列表

int foo(int a, int b) ---逗号分隔的参数列表

Foo::Foo() : a(5), b(3) {} ---类构造函数中的逗号分隔的初始化列表


*如果您应用优化,则不完全正确.如果编译器认识到某段代码对其余代码完全没有影响,它将删除不必要的语句.

进一步阅读:http://en.wikipedia.org/wiki/Comma_o​​perator


这个答案应该是公认的答案!感谢您的全面参考!

5> MobyDX..:

a将是b,但表达式的值将是c.也就是说,在

d = (a = b, c);

a等于b,d等于c.


差不多正确.表达式没有值,表达式也没有.该表达式的值是c.

6> prakash..:

b的值将被分配给a.什么都不会发生在c

推荐阅读
wangtao
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有