【问题标题】:Some confusion with how commas work in C/C++ [duplicate]对逗号在 C/C++ 中的工作方式有些困惑 [重复]
【发布时间】:2015-04-08 22:12:12
【问题描述】:

我使用 SO 作为参考已有一段时间了,但之前从未问过问题。我目前正在上大学的 C++ 课程,并且正在阅读 Bjarne Stroutstrup 的Programming: Principles and Practice,只是为了我自己的利益,因为我在这里看到了一个真正推荐它的问题的答案。

目前我们正在课堂上讨论运算符,但我似乎无法理解逗号运算符在语句中的工作原理。一个例子是课程在线部分的一个示例问题,即使我编写了一个 C 程序并使用 GDB 来获得结果,我也会一直出错。问题是:

假设在下面的表达式之前x==16,那么下面的表达式的值是多少(不一定是x的值)?

x++, ++x, x+=x

我对正确答案的兴趣并不在于如何获得正确答案。我已经阅读了几个类似问题的答案,例如这个here,但似乎我错过了当实际上没有分配运算符时这是如何应用的。这和说的一样吗

int y = (x++, ++x, x+=x);

int y = x++, ++x, x+=x;

或者两者都不是?有人可以解释一下逗号运算符是如何工作的,特别是与没有赋值的语句有关吗?

【问题讨论】:

  • @SouravGhosh 不,逗号运算符在其操作数之间引入了一个序列点。表达式从左到右排序。
  • @KeithThompson 谢谢先生纠正我。
  • @juanchopanza 先生,不知怎的,我错过了第 6.5.17 章。对于那个很抱歉。我的立场是正确的。
  • @ArunA.S 如果行为未定义或未指定,这将无济于事。
  • 请注意 int y = x++, ++x, x+=x; 不会编译。

标签: c++ c operator-keyword operator-precedence comma-operator


【解决方案1】:

逗号操作符很简单——简单到很难。它在所有算子中优先级最低;它的优先级甚至低于赋值运算符。请注意,函数的参数不使用逗号分隔符。

逗号运算符计算其左侧操作数,生成一个序列点并丢弃结果,然后计算右侧操作数。

在上下文中:

x++, ++x, x += x;

相当于:

x++;
++x;
x += x;

除了整体值是x += x;的结果。

假设 x 从 16 开始,它会递增到 17,然后是 18,然后加倍到 36。因此,总值为 36。

请注意,由于序列点,它不会违反关于在序列点之间不多次递增同一变量的规则。

真正使用逗号运算符的唯一原因是在某些上下文中您不能使用单独的语句,但可以使用逗号运算符。例如:

for (i = 0, j = n; i < j; ++i, --j)

您不能使用分号代替这些逗号。


在问题中,有两个样本:

int y = (x++, ++x, x+=x);

int y = x++, ++x, x+=x;

第一个是合法的(尽管不必要地扭曲了),并将 y 初始化为 36(并将 x 设置为 36)。

第二个是不合法的,不会编译;逗号不是逗号运算符,应该分隔不同的声明符,但 ++xx += x 不是声明符。但是,如果改为:

y = x++, ++x, x+=x;

那么这将是合法的。第一项是:

y = x++

将 16 分配给 y 并将 x 递增到 17。第二项将 x 递增到 18;第三项将 x 更改为 36。

【讨论】:

  • Klas Lindbäck — 感谢您的编辑;当您进行更改时,我是在规则之后添加材料的一部分。我希望我的解释至少和你的一样好。我已经在答案的最顶部指出,逗号运算符的优先级甚至低于赋值。
【解决方案2】:

逗号运算符计算第一个操作数,丢弃它,然后计算 第二个,计算之间有一个序列点。

在你的情况下,这意味着你已经评估了这个表达式序列

x++   // evaluates to 16, increments x to 17
++x   // increments x to 18, evaluates to 18
x+=x  // increments x by x, i.e. by 18, evaluates to 36.

完整的表达式计算为第三个子表达式。第一个表达式计算为 16,但将 x 增加到 17。第二个表达式将 x 增加到 18 并计算为该数字。第三个将 x 的值增加 18,计算结果为 x,即计算结果为 36。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-24
    • 2019-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多