逗号运算符如何工作以及它有什么优先级?

发布于 2024-07-05 03:44:30 字数 500 浏览 10 评论 0原文

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

例如,如果我这样做:

a = b, c;  

a 最终等于 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;

How does the comma operator work in C++?

For instance, if I do:

a = b, c;  

Does a end up equaling b or 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;

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

七堇年 2024-07-12 03:44:30

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

#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

众所周知,逗号运算符的优先级低于赋值......

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
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

As we know comma operator has lower precedence than assignment.....

夜唯美灬不弃 2024-07-12 03:44:30

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

The value of a will be equal to b, since the comma operator has a lower precedence than the assignment operator.

猫瑾少女 2024-07-12 03:44:30

首先要做的事情:逗号实际上不是一个运算符,对于编译器来说,它只是一个标记,可以在上下文中与其他标记一起获得含义。

这意味着什么以及为什么要这么麻烦?

示例 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;

因为优先级= 令牌/运算符的 a> 优先级高于 , 令牌。

这是在上下文中解释的

a = b;
c;

(请注意,解释取决于上下文,这里它既不是函数/方法调用,也不是模板实例化。)

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:

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.

The correct interpretation of the example above is of course that it is an instatiation of a template.

Example 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(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.

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).

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.)

无可置疑 2024-07-12 03:44:30

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

b's value will be assigned to a.
Nothing will happen to c

浅紫色的梦幻 2024-07-12 03:44:30

它等于b

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

It would be equal to b.

The comma operator has a lower precedence than assignment.

满天都是小星星 2024-07-12 03:44:30

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

d = (a = b, c);

a 等于 bd 等于 c

The value of a will be b, but the value of the expression will be c. That is, in

d = (a = b, c);

a would be equal to b, and d would be equal to c.

迷雾森÷林ヴ 2024-07-12 03:44:30

逗号运算符:

  • 优先级最低的
  • 是左关联

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

  • < code>exprA 被计算
  • exprA 的结果被忽略
  • exprB 被计算
  • exprB 的结果作为结果返回整个表达式

对于大多数运算符,编译器可以选择执行顺序,甚至需要在不影响最终结果的情况下跳过执行(例如 false && foo() 将跳过对 foo 的调用)。 然而,逗号运算符的情况并非如此,上述步骤总是会发生*

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

  • C 语法需要单个表达式,而不是语句。 例如,在 if( HERE )
  • C 语法需要单个语句,而不是更多语句,例如在 for 循环的初始化中 for ( HERE ; ; )
  • 当你想跳过大括号并保留单个语句时: if (foo) HERE ; (请不要这样做,这真的很难看!)

当语句不是表达式时,分号不能替换为逗号。 例如,这些是不允许的:

  • (foo, if (foo) bar)if 不是表达式)
  • x, int y (变量声明不是表达式)

int 您的情况我们有:

  • a=b, c;,相当于a=b; c;,假设 a 的类型不会重载逗号运算符。
  • a = b, c = d; 相当于 a=b; c=d;,假设 a 的类型不会重载逗号运算符。

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

  • int a, b; --- 变量声明列表是逗号分隔的,但这些不是逗号运算符
  • int a=5, b=3;< /code> --- 这也是一个逗号分隔的变量声明列表
  • foo(x,y) --- 逗号分隔的参数列表。 事实上,xy 可以按任何顺序进行计算!
  • FOO(x,y) --- 逗号分隔的宏参数列表
  • foo --- 逗号分隔的模板参数列表
  • int foo( int a, int b) --- 逗号分隔的参数列表
  • Foo::Foo() : a(5), b(3) {} --- 逗号分隔的初始值设定项list in a class constructor

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

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

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 is evaluated
  • the result of exprA is ignored
  • exprB is evaluated
  • the result of exprB is returned as the result of the whole expression

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 (e.g. false && foo() will skip the call to 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. e.g. in if( HERE )
  • C syntax requires a single statement, not more, e.g. in the initialization of the for loop for ( HERE ; ; )
  • When you want to skip curly braces and keep a single statement: 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)
  • int x, int y (variable declaration is not an expression)

In your case we have:

  • a=b, c;, equivalent to a=b; c;, assuming that a is of type that does not overload the comma operator.
  • a = b, c = d; equivalent to a=b; c=d;, assuming that a is of type that does not overload the comma operator.

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. In fact, x and y can be evaluated in any order!
  • FOO(x,y) --- comma-separated macro argument list
  • foo<a,b> --- comma-separated template argument list
  • int foo(int a, int b) --- comma-separated parameter list
  • Foo::Foo() : a(5), b(3) {} --- comma-separated initializer list in a class constructor

* 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

最偏执的依靠 2024-07-12 03:44:30

请注意,逗号运算符在 C++ 中可能会重载。 因此,实际行为可能与预期有很大不同。

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

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

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

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

与> 它返回一个代理对象,在该代理对象上调用其余的运算符:

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

Take care to notice that the comma operator may be overloaded in 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. 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 ,("or").operator ,("not").operator ,("xor");
似狗非友 2024-07-12 03:44:30

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

a = b, c;

相当于:

(a = b), c;

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

a+b, c(), d

保证按顺序计算其三个子表达式(a+bc()d)。 如果它们有副作用,这一点就很重要了。 通常,编译器可以按照他们认为合适的任何顺序来计算子表达式; 例如,在函数调用中:

someFunc(arg1, arg2, arg3)

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

The comma operator has the lowest precedence of all C/C++ operators. 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. 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文