-1

为什么以下代码会产生此输出:

代码片段:

int a=10;
printf("%d%d%d",++a,a++,++a);

输出:

131113

如何评估参数?这是否取决于编译器?我使用 gcc 编译器。谁能告诉我我的编译器是如何评估它的?如果编译器从右到左评估函数的参数,则此代码的输出将如下所示:

121111
4

2 回答 2

2

那是未定义的行为。在序列点中多次修改变量是未定义行为。

来自维基:

序列点定义了计算机程序执行中的任何点,在该点处,可以保证先前评估的所有副作用都已执行,并且尚未执行后续评估的任何副作用。

请阅读:运算符优先级与评估顺序

如需全面了解,请阅读:未定义的行为和序列点

你可以这样做:

int a=10;
int b = (++a,a++,++a);

因为逗号 (,) 在这里是一个运算符,而不仅仅是参数之间的分隔符,例如printf.

于 2013-10-03T07:28:39.160 回答
1

这实际上是未指定行为未定义行为的组合。

这是未指定的,因为在此行中未指定函数参数的评估顺序:

printf("%d%d%d",++a,a++,++a);
       ^        ^   ^   ^
       1        2   3   4

我们不知道将评估哪些订单函数参数14甚至有可能如果这是在一个循环中,那么在随后的执行中,订单可能会有所不同。这在 C99 草案标准部分“6.5.2.2 函数调用”第10段中有所介绍,其中说(强调我的):

函数指示符、实际参数和实际参数中的子表达式的求值顺序是未指定的在实际调用之前有一个序列点。

就其本身而言,这意味着程序的输出是不可靠的,但我们也有未定义的行为,因为上面的代码在一个序列点a内多次修改。这在表达式2节中涵盖,其中说(强调我的):6.5

在前一个和下一个序列点之间,对象的存储值最多只能通过表达式的评估修改一次。72)此外,应仅读取先验值以确定要存储的值。73)

未定义的行为意味着运行此程序可能会导致任何结果,包括它似乎可以正常工作,该术语在部分中定义3.4.3并包括以下注释,该注释解释了未定义行为的可能结果:

可能的未定义行为范围从完全忽略具有不可预测结果的情况,到在翻译或程序执行期间以环境特征的记录方式表现(有或没有发出诊断消息),到终止翻译或执行(有发出的诊断消息)。

除此之外,即使您可以获得可靠的结果,这样的代码也很难阅读,并且在复杂的项目中维护将是一场噩梦。如果有其他更简单的方法来编写满足其他要求(例如性能等)的代码......那么这就是您应该采用的方法。

于 2013-10-03T14:09:38.357 回答