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;
有帮助吗?

解决方案

它等于 b.

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

其他提示

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

举个例子, 精神振奋 非常巧妙地使用逗号运算符来实现符号表的列表初始值设定项。因此,它使得以下语法成为可能并且有意义:

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

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

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

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

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

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

a = b, c;

相当于:

(a = b), c;

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

a+b, c(), d

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

someFunc(arg1, arg2, arg3)

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

逗号运算符:

  • 优先级最低
  • 是左结合的

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

  • exprA 被评估
  • 的结果 exprA 被忽略
  • exprB 被评估
  • 的结果 exprB 作为整个表达式的结果返回

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

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

  • C 语法需要一个 表达, ,不是一个声明。例如在 if( 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) --- 逗号分隔的参数列表。实际上, xy 可以评估为 任何 命令!
  • FOO(x,y) --- 逗号分隔的宏参数列表
  • foo<a,b> --- 逗号分隔的模板参数列表
  • int foo(int a, int b) --- 逗号分隔的参数列表
  • Foo::Foo() : a(5), b(3) {} --- 类构造函数中以逗号分隔的初始值设定项列表

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

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

的价值 ab, ,但值 表达方式c. 。也就是说,在

d = (a = b, c);

a 等于 b, , 和 d 将等于 c.

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

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

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

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

输出 :我=3
因为逗号运算符总是返回最右边的值。
如果逗号运算符与赋值运算符一起使用:

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

输出:我=1
众所周知,逗号运算符的优先级低于赋值......

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

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

示例1:

为了理解不同上下文中相同标记的含义之间的差异,我们看一下这个例子:

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

通常 C++ 初学者会认为这个表达式可以/会比较事物,但这是绝对错误的, <, >, 令牌取决于使用上下文。

对上面例子的正确解释当然是它是模板的实例化。

示例2:

当我们编写一个典型的 for 循环时,它具有多个初始化变量和/或多个表达式,这些表达式应该在循环的每次迭代之后完成,我们也使用逗号:

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

逗号的含义取决于使用上下文,这里是上下文 for 建造。

上下文中的逗号实际上意味着什么?

让事情变得更加复杂(就像在 C++ 中一样),逗号运算符本身可以被重载(感谢 康拉德·鲁道夫 指出这一点)。

回到问题,代码

a = b, c;

对于编译器来说意味着类似

(a = b), c;

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

这在上下文中解释为

a = b;
c;

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top