逗号运算符如何在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;
答案 0 :(得分:124)
请注意,逗号运算符可能在C ++中过载。因此,实际行为可能与预期的非常不同。
作为示例,Boost.Spirit非常巧妙地使用逗号运算符来实现符号表的列表初始值设定项。因此,它使以下语法成为可能和有意义的:
keywords = "and", "or", "not", "xor";
请注意,由于运算符优先级,代码(有意!)与
相同(((keywords = "and"), "or"), "not"), "xor";
也就是说,第一个调用的运算符是keywords.operator =("and")
,它返回一个代理对象,在该代理对象上调用剩余的operator,
:
keywords.operator =("and").operator ,("or").operator ,("not").operator ,("xor");
答案 1 :(得分:120)
逗号运算符具有所有C / C ++运算符的最低优先级。因此,它始终是绑定到表达式的最后一个,这意味着:
a = b, c;
相当于:
(a = b), c;
另一个有趣的事实是逗号运算符引入了sequence point。这意味着表达式:
a+b, c(), d
保证按顺序评估其三个子表达式( a + b , c()和 d )。如果它们有副作用,这是很重要的。通常,编译器可以按照他们认为合适的顺序评估子表达式;例如,在函数调用中:
someFunc(arg1, arg2, arg3)
参数可以按任意顺序进行评估。请注意,函数调用中的逗号是不是运算符;他们是分隔符。
答案 2 :(得分:73)
等于b
。
逗号运算符的优先级低于赋值。
答案 3 :(得分:62)
逗号运算符:
为所有类型(内置和自定义)定义了逗号运算符的默认版本,它的工作方式如下 - 给定exprA , exprB
:
exprA
exprA
的结果exprB
exprB
的结果
对于大多数运算符,允许编译器选择执行顺序,如果它不影响最终结果,甚至需要跳过执行(例如false && foo()
将跳过对{{1的调用}})。然而,逗号运算符并非如此,上述步骤将始终发生在 * 。
实际上,默认逗号运算符的工作方式与分号几乎相同。不同之处在于,由分号分隔的两个表达式形成两个单独的语句,而逗号分隔将所有表达式保留为单个表达式。这就是为什么逗号运算符有时用于以下场景:
foo
if( HERE )
循环for
for ( HERE ; ; )
(请不要这样做,这真的太丑了!)如果语句不是表达式,则分号不能用逗号替换。例如,这些是不允许的:
if (foo) HERE ;
((foo, if (foo) bar)
不是表达式)在你的情况下,我们有:
if
,相当于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<a,b>
---以逗号分隔的参数列表int foo(int a, int b)
---类构造函数中的逗号分隔初始化列表* 如果您应用优化,则不完全正确。如果编译器认识到某段代码对其余代码完全没有影响,它将删除不必要的语句。
答案 4 :(得分:37)
a
的值为b
,但 表达式 的值为c
。也就是说,
d = (a = b, c);
a等于b
,d
等于c
。
答案 5 :(得分:8)
b的值将被分配给a。 c
什么都不会发生答案 6 :(得分:2)
a的值将等于b,因为逗号运算符的优先级低于赋值运算符。
答案 7 :(得分:2)
是逗号运算符的优先级低于赋值运算符
#include<stdio.h>
int main()
{
int i;
i = (1,2,3);
printf("i:%d\n",i);
return 0;
}
输出:i = 3
因为逗号运算符总是返回最右边的值
对于具有赋值运算符的逗号运算符:
int main()
{
int i;
i = 1,2,3;
printf("i:%d\n",i);
return 0;
}
输出:i = 1
我们知道逗号运算符的优先级低于赋值.....
答案 8 :(得分:-3)
首先要做的事情:逗号实际上不是运算符,对于编译器来说,它只是一个令牌,它在上下文中获得含有其他令牌的含义
。示例1:
要理解不同上下文中同一令牌的含义之间的区别,我们来看看这个例子:
class Example {
Foo<int, char*> ContentA;
}
通常一个C ++初学者会认为这个表达式可以/会比较一些事情,但它绝对是错误的,<
,>
和,
令牌的含义取决于使用
上述示例的正确解释当然是模板的实例化。
示例2:
当我们编写一个带有多个初始化变量的典型for循环和/或在循环的每次迭代后应该完成的多个表达式时,我们也使用逗号:
for(a=5,b=0;a<42;a++,b--)
...
逗号的含义取决于使用的上下文,这里是for
构造的上下文。
为了使它更复杂(如在C ++中一样),逗号运算符本身可以被重载(感谢Konrad Rudolph指出它)。
回到问题,代码
a = b, c;
对于编译器来说意味着类似
(a = b), c;
因为=
令牌/运算符的priority高于,
令牌的优先级。
,这在上下文中解释,如
a = b;
c;
(请注意,解释取决于上下文,此处它既不是函数/方法调用,也不是模板实例。)