在函数参数中使用前缀和后缀运算符时会产生不同且奇怪的结果

Different and odd results when using prefix and postfix operators in function arguments

代码:

#include <stdio.h>

int main()
{
    int i = 3;
    printf("%d %d %d %d %d\n",i = 7,--i,i = 18, i+5, i = 0);
    printf("%d %d %d %d %d\n",i = 7,i--,i = 18, i+5, i = 0);

    return 0;
}  

输出:

7 7 7 5 7
7 18 7 5 7

为什么我得到这个输出,谁能给我解释一下 printf 语句中的这些表达式是如何执行的?

我的意思是,编译器考虑的顺序是什么?

这是一个非常奇怪的代码,你不应该渴望写这样的代码,它会带来不必要的混乱。

可以根据编译器设置以任何顺序计算函数参数,因此此代码的输出可能因编译器和设置而异。

我假设你在某个学校看到过这段代码class,这种类型的例子通常在老师试图解释post-increment 和pre-increment 时出现。

请理解前增量和post-增量差异拳:

  • ++x(pre-increment)意思是“增加变量;变量的值 表达式是最终值
  • x++(post-increment)意思是“记住原来的值,然后 增加变量;表达式的值是原来的 价值

编辑:更改说明以免造成混淆,输出可能因多个变量而异。

这里的 big 问题是 i 中所做的更改由于缺少序列而调用未定义的行为点.

表现出未定义行为的程序对编译过程应该如何发生没有任何要求,编译器可以按其认为合适的方式处理它,不同的编译器甚至同一编译器的不同版本会产生不同的结果。

虽然这不是必需的,但他们通常做的一件事是产生一些警告,前提是启用了警告标志,有些甚至不需要,demo

相关标准词条:

N1570 ISO/IEC 9899:201x C11

§6.5 Expressions:

2 - If a side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object, the behavior is undefined. If there are multiple allowable orderings of the subexpressions of an expression, the behavior is undefined if such an unsequenced side effect occurs in any of the orderings.

需要说明的是,逗号运算符不是一个序列点。

我还应该注意,函数参数的计算顺序是未指定的。

§6.5.2.2 Function calls

10 - There is a sequence point after the evaluations of the function designator and the actual arguments but before the actual call. Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function.

正如已经指出的那样,这不是您应该向任何人展示的代码,当然在这种情况下是出于学习目的。

参数的计算顺序未指定,对同一对象的未排序修改具有未定义的行为。

因此,正式地,对您的代码进行推理是没有意义的。

然而,它是可以解释的,从右边进行评估,而不是非理性或随机的。
(请注意,大多数参数与传递 i 相同;i = 18“是”i,而不是 18。)

第一个:

i = 0;
int new_variable = i + 5;
i = 18;
i -= 1;
i = 7;
printf("%d %d %d %d %d\n", i, i, i, new_variable, i);

第二个:

i = 0;
int new_variable = i + 5;
i = 18;
int previous_i = i;
i = 7;
printf("%d %d %d %d %d\n", i, previous_i, i, new_variable, i);
i -= 1;