简体   繁体   English

逗号运算符如何工作

[英]How does the Comma Operator work

How does the comma operator work in C++?逗号运算符在 C++ 中如何工作?

For instance, if I do:例如,如果我这样做:

a = b, c;  

Does a end up equaling b or c? a 是否等于 b 或 c?

(Yes, I know this is easy to test - just documenting on here for someone to find the answer quickly.) (是的,我知道这很容易测试 - 只需在此处记录以供某人快速找到答案。)

Update: This question has exposed a nuance when using the comma operator.更新:这个问题暴露了使用逗号运算符时的细微差别。 Just to document this:只是为了记录这一点:

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

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

This question was actually inspired by a typo in code.这个问题实际上是受到代码中的错字的启发。 What was intended to be本来打算是什么

a = b;
c = d;

Turned into转换成

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

Take care to notice that the comma operator may be overloaded in C++.请注意逗号运算符可能在 C++ 中被重载。 The actual behaviour may thus be very different from the one expected.因此,实际行为可能与预期的非常不同。

As an example, Boost.Spirit uses the comma operator quite cleverly to implement list initializers for symbol tables.例如, Boost.Spirit非常巧妙地使用逗号运算符来实现符号表的列表初始值设定项。 Thus, it makes the following syntax possible and meaningful:因此,它使以下语法成为可能且有意义:

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

Notice that due to operator precedence, the code is (intentionally!) identical to请注意,由于运算符优先级,代码(故意!)与

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

That is, the first operator called is keywords.operator =("and") which returns a proxy object on which the remaining operator, s are invoked:也就是说,调用的第一个运算符是keywords.operator =("and") ,它返回一个代理对象,在该对象上调用剩余的operator, s:

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

The comma operator has the lowest precedence of all C/C++ operators.逗号运算符在所有 C/C++ 运算符中的优先级最低 Therefore it's always the last one to bind to an expression, meaning this:因此,它始终是绑定到表达式的最后一个,这意味着:

a = b, c;

is equivalent to:相当于:

(a = b), c;

Another interesting fact is that the comma operator introduces a sequence point .另一个有趣的事实是逗号运算符引入了一个序列点 This means that the expression:这意味着表达式:

a+b, c(), d

is guaranteed to have its three subexpressions ( a+b , c() and d ) evaluated in order.保证按顺序计算其三个子表达式( a+bc()d )。 This is significant if they have side-effects.如果它们有副作用,这很重要。 Normally compilers are allowed to evaluate subexpressions in whatever order they find fit;通常允许编译器以他们认为合适的任何顺序来评估子表达式。 for example, in a function call:例如,在函数调用中:

someFunc(arg1, arg2, arg3)

arguments can be evaluated in an arbitrary order.可以按任意顺序评估参数。 Note that the commas in the function call are not operators;请注意,函数调用中的逗号不是运算符; they are separators.它们是分隔符。

It would be equal to b .它将等于b

The comma operator has a lower precedence than assignment.逗号运算符的优先级低于赋值。

The comma operator:逗号运算符:

  • has the lowest precedence具有最低优先级
  • is left-associative是左结合的

A default version of comma operator is defined for all types (built-in and custom), and it works as follows - given exprA , exprB :为所有类型(内置和自定义)定义了逗号运算符的默认版本,它的工作方式如下 - 给定exprA , exprB

  • exprA is evaluated exprA被评估
  • the result of exprA is ignored exprA的结果被忽略
  • exprB is evaluated exprB被评估
  • the result of exprB is returned as the result of the whole expression exprB的结果作为整个表达式的结果返回

With most operators, the compiler is allowed to choose the order of execution and it is even required to skip the execution whatsoever if it does not affect the final result (eg false && foo() will skip the call to foo ).对于大多数操作符,允许编译器选择执行顺序,甚至在不影响最终结果的情况下甚至需要跳过执行(例如false && foo()将跳过对foo的调用)。 This is however not the case for comma operator and the above steps will always happen * .但是,逗号运算符并非如此,上述步骤将始终发生*

In practice, the default comma operator works almost the same way as a semicolon.在实践中,默认逗号运算符的工作方式几乎与分号相同。 The difference is that two expressions separated by a semicolon form two separate statements, while comma-separation keeps all as a single expression.不同之处在于,用分号分隔的两个表达式形成两个单独的语句,而逗号分隔将所有表达式保留为一个表达式。 This is why comma operator is sometimes used in the following scenarios:这就是为什么有时会在以下场景中使用逗号运算符的原因:

  • C syntax requires an single expression , not a statement. C 语法需要单个表达式,而不是语句。 eg in if( HERE )例如在if( HERE )
  • C syntax requires a single statement, not more, eg in the initialization of the for loop for ( HERE ; ; ) C 语法需要一个语句,而不是更多,例如在for循环的初始化中for ( HERE ; ; )
  • When you want to skip curly braces and keep a single statement: if (foo) HERE ;当您想跳过花括号并保留一条语句时: if (foo) HERE ; (please don't do that, it's really ugly!) (请不要那样做,真的很丑!)

When a statement is not an expression, semicolon cannot be replaced by a comma.当语句不是表达式时,分号不能用逗号代替。 For example these are disallowed:例如,这些是不允许的:

  • (foo, if (foo) bar) ( if is not an expression) (foo, if (foo) bar) ( if不是表达式)
  • int x, int y (variable declaration is not an expression) int x, int y(变量声明不是表达式)

In your case we have:在您的情况下,我们有:

  • a=b, c; , equivalent to a=b; c; , 等价于a=b; c; a=b; c; , assuming that a is of type that does not overload the comma operator. ,假设a的类型不会重载逗号运算符。
  • a = b, c = d; equivalent to a=b; c=d;相当于a=b; c=d; a=b; c=d; , assuming that a is of type that does not overload the comma operator. ,假设a的类型不会重载逗号运算符。

Do note that not every comma is actually a comma operator.请注意,并非每个逗号实际上都是逗号运算符。 Some commas which have a completely different meaning:一些具有完全不同含义的逗号:

  • int a, b; --- variable declaration list is comma separated, but these are not comma operators --- 变量声明列表以逗号分隔,但这些不是逗号运算符
  • int a=5, b=3; --- this is also a comma separated variable declaration list --- 这也是一个逗号分隔的变量声明列表
  • foo(x,y) --- comma-separated argument list. foo(x,y) --- 逗号分隔的参数列表。 In fact, x and y can be evaluated in any order!事实上, xy可以按任何顺序计算!
  • FOO(x,y) --- comma-separated macro argument list FOO(x,y) --- 逗号分隔的宏参数列表
  • foo<a,b> --- comma-separated template argument list foo<a,b> --- 逗号分隔的模板参数列表
  • int foo(int a, int b) --- comma-separated parameter list int foo(int a, int b) --- 逗号分隔的参数列表
  • Foo::Foo() : a(5), b(3) {} --- comma-separated initializer list in a class constructor Foo::Foo() : a(5), b(3) {} --- 类构造函数中逗号分隔的初始化列表

* This is not entirely true if you apply optimizations. *如果您应用优化,这并不完全正确。 If the compiler recognizes that certain piece of code has absolutely no impact on the rest, it will remove the unnecessary statements.如果编译器认识到某段代码对其余部分完全没有影响,它将删除不必要的语句。

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

The value of a will be b , but the value of the expression will be c . a的值为b ,但表达式的值为c That is, in也就是说,在

d = (a = b, c);

a would be equal to b , and d would be equal to c . a等于bd等于c

b's value will be assigned to a. b 的值将分配给 a。 Nothing will happen to c c 什么都不会发生

Yes Comma operator has low precedence than Assignment operator是 逗号运算符的优先级低于赋值运算符

#include<stdio.h>
int main()
{
          int i;
          i = (1,2,3);
          printf("i:%d\n",i);
          return 0;
}

Output : i=3输出:i=3
Because comma operator always return rightmost value.因为逗号运算符总是返回最右边的值。
In case of comma operator with Assignment Operator:如果逗号运算符带有赋值运算符:

 int main()
{
      int i;
      i = 1,2,3;
      printf("i:%d\n",i);
      return 0;
}

Ouput: i=1输出:i=1
As we know comma operator has lower precedence than assignment.....正如我们所知,逗号运算符的优先级低于赋值......

a 的值将等于 b,因为逗号运算符的优先级低于赋值运算符。

First things first: Comma is actually not an operator, for the compiler it is just a token which gets a meaning in context with other tokens.首先要做的事情:逗号实际上不是运算符,对于编译器来说,它只是一个标记,它在与其他标记的上下文中获得意义。

What does this mean and why bother?这是什么意思,为什么要打扰?

Example 1:示例 1:

To understand the difference between the meaning of the same token in a different context we take a look at this example:为了理解不同上下文中相同标记的含义之间的差异,我们看一下这个例子:

class Example {
   Foo<int, char*> ContentA;
}

Usually a C++ beginner would think that this expression could/would compare things but it is absolutly wrong, the meaning of the < , > and , tokens depent on the context of use.通常 C++ 初学者会认为这个表达式可以/会比较事物,但这是绝对错误的, <>,标记的含义取决于使用的上下文。

The correct interpretation of the example above is of course that it is an instatiation of a template.对上面例子的正确解释当然是它是一个模板的实例化。

Example 2:示例 2:

When we write a typically for loop with more than one initialisation variable and/or more than one expressions that should be done after each iteration of the loop we use comma too:当我们编写一个具有多个初始化变量和/或多个表达式的典型 for 循环时,应该在循环的每次迭代后完成,我们也使用逗号:

for(a=5,b=0;a<42;a++,b--)
   ...

The meaning of the comma depends on the context of use, here it is the context of the for construction.逗号的含义取决于使用的上下文,这里是for构造的上下文。

What does a comma in context actually mean?上下文中的逗号实际上是什么意思?

To complicate it even more (as always in C++) the comma operator can itself be overloaded (thanks to Konrad Rudolph for pointing that out).更复杂的是(在 C++ 中总是如此),逗号运算符本身可以被重载(感谢Konrad Rudolph指出这一点)。

To come back to the question, the Code回到这个问题,守则

a = b, c;

means for the compiler something like对编译器来说意味着类似

(a = b), c;

because the priority of the = token/operator is higher than the priority of the , token.因为=令牌/运算符的 优先级高于,令牌的优先级。

and this is interpreted in context like这在上下文中被解释为

a = b;
c;

(note that the interpretation depend on context, here it it neither a function/method call or a template instatiation.) (请注意,解释取决于上下文,这里它既不是函数/方法调用也不是模板实例化。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM