以下程序的输出是什么,为什么?
#include<stdio.h>
#include<conio.h>
int main()
{
int a=5;
a +=a += a += 2;
printf("%d",a);
getch();
return 0;
}
答案 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 += 2
或x += 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