C中的复合赋值运算符

时间:2018-05-30 10:53:03

标签: c operators

以下程序的输出是什么,为什么?

#include<stdio.h>
#include<conio.h>
int main()
{
    int a=5;
    a +=a += a += 2;
    printf("%d",a);
    getch();
    return 0;
}

3 个答案:

答案 0 :(得分:1)

当您在未经过排序的步骤中读取和写入a时,您的程序行为未定义

您的古代编译器正在执行的操作是正确遵循C语法规则并表达式分组为

a += (a += (a += 2))

但分组排序相同。从这一点来看,行为是不确定的。您的编译器似乎将上面的内容评估为

a += (a += 7)

接着是

a += 14

获得28

答案 1 :(得分:0)

这是一个棘手的问题,没有一个简单明了的答案。

表达式可能未定义,在这种情况下,询问“可能的输出是什么?”是没有意义的,因为它可能是任何

如果它未定义,那是因为有a的多个写入(存储)没有任何中间序列点。最右边的a += 2计算7并准备将其存储到a中。接下来我们有中间a +=,试图取7并将其添加到......什么? a的旧值或新值?如果它是旧的我们计算5 + 7 = 12并且如果它是新的我们计算7 + 7 = 14,并且无论我们计算哪个值,我们准备将存储到a,但是它会“赢”并覆盖最右边a += 2试图存储的值吗?然后,争论(以及不同解释和可能答案的多样性)扩散到最左边的a +=

当然,并非所有赋值表达式都是未定义的。例如,旧备用

a = a + 1

定义明确。它都是从a获取并分配给a,但在这种情况下,我们不必询问,“如果它在从a获取之前分配给它是什么?”,因为很明显,在计算要分配的新值的过程中,首先从a获取。但是这个论点并没有拯救a += a += 2,我不认为。

有关于“排序”的新规则废除了“序列点”的旧概念,新规则可能会使这个表达式定义明确,但我不确定。

除非你对令人沮丧的,令人头疼的谜题感兴趣,否则最好避开像这样的表情。你显然不会在真正的程序中使用这样的表达式。几乎不可能弄清楚(a)表达式是否定义明确,(b)如果是,它应该做什么,所以包含这样的表达式的程序是不可维护的;你必须成为一名核心语言律师才能正确理解它。

自然,理解像a += 2x += y[i++]这样更简单,更健全的表达方式是很重要的。但是对于像a += a += a += 2那样疯狂的事情,不要陷入这样的陷阱:“如果我理解它意味着什么,它会不会帮助我更好地理解C?”,因为唯一要理解的是它的边界,如果不是绝对的,毫无意义。

另请参阅SO关于未定义表达式的规范条目Why are these constructs (using ++) undefined behavior in C?(尽管这些答案都没有涵盖此特定情况)。

答案 2 :(得分:-6)

这取决于编译器!但理论上28就是答案! 作业将从右到左进行,因此a +=a += a += 2;可以分解为

5+2=7 a+=2
7+7=14 a+=a+=2
14+14=28 a+=a+=a+=2