增量算子的行为作为函数的参数

时间:2013-10-03 07:27:26

标签: c parameters increment

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

代码段:

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

输出:

131113

如何评估参数?这取决于编译器吗?我用gcc编译器。谁能告诉我我的编译器如何评估它?如果编译器从右到左计算函数的参数,那么此代码的输出将如下:

121111

2 个答案:

答案 0 :(得分:2)

那是未定义的行为。在sequence point中多次修改变量是未定义行为。

来自维基:

  

序列点定义计算机程序执行中的任何点   保证以前的所有副作用   评估将会进行,没有副作用   后来的评估工作尚未完成。

请阅读:Operator Precedence vs Order of Evaluation

如需全面了解,请阅读:Undefined Behavior and Sequence Points

你可以这样做:

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

因为逗号(,)是这里的运算符而只是参数之间的分隔符,如printf的情况。

答案 1 :(得分:1)

这实际上是unspecified behaviorundefined behavior的组合。

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

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

我们不知道将对14的哪个顺序函数进行评估,如果这是一个循环,在后续执行中,顺序可能会有所不同。这在C99草案标准部分6.5.2.2 函数调用 10 中有所说明(强调我的):

  

评估函数指示符的顺序,实际参数,和   实际参数中的子表达式未指定,但有一个序列点   在实际通话之前。

这本身意味着程序的输出不可靠但我们还有未定义的行为,因为上面的代码在sequence point内多次修改a 。这部分由6.5 表达式段落 2 表示(强调我的):

  

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

未定义的行为表示运行此程序可能会导致任何事情,包括它似乎正常工作,该术语在3.4.3部分中定义并包含以下 note ,它解释了未定义行为的可能结果

  

可能的未定义行为包括完全忽略具有不可预测结果的情况,在转换或程序执行期间以环境特征(有或没有发出诊断消息)的文档方式执行,终止翻译或执行(发布诊断信息)。

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