执行printf(..)参数的顺序是什么?

时间:2019-02-06 19:06:14

标签: c printf

我想做类似printf("%d,%d",array[c], array[c+1])的事情,每个迭代中只有一个变量增加。我编写了以下代码,并期望将“ 1,2”输入标准输出,这是错误的:

#include <stdio.h>
int main()
{
    int c = 1;
    printf("%d,%d",c++,c++); /* 2,1 */
    //printf("%d,%d",c,c++);   /* 2,1 */
    //printf("%d,%d",c++,c);   /* 1,2 */
}

如果我尝试执行printf("%d,%d",c++,c)printf("%d,%d",c,c++),则可以看到“ c ++”语句没有定义的执行顺序。

有人可以解释我编写的代码如何编译吗?以及为什么以及如何根据“ c ++”语句的位置进行更改。

3 个答案:

答案 0 :(得分:5)

函数调用中的参数求值顺序不确定, 这些表达式的求值之间没有序列点。这意味着-如果一个表达式以副作用的形式更改了对象(例如c的值),而该对象也被另一个表达式访问,则这些表达式的结果将是不可预测的。因此,该语言将以下情况定义为未定义的行为(例如,this在线C标准草案):

  

6.5表达式

     

2。)如果相对于标量对象的副作用没有顺序   对相同标量对象或值的不同副作用   使用相同标量对象的值进行计算,其行为是   未定义。 ...

答案 1 :(得分:3)

函数参数的求值顺序未指定。由于++运算符具有副作用-在一个表达式(函数调用)中产生两个副作用是未定义的行为。

答案 2 :(得分:1)

C参数未定义对函数参数进行求值的顺序。参数传递到函数的顺序通常由调用约定定义,尽管仍然将评估顺序留给编译器。

例如,如果您有一个调用约定,其中参数从右向左推入堆栈(这在x86-32上很普遍),则为printf("%d %d", c, c++);生成的程序集可能看起来像:

push eax ; arg 3
push edx ; arg 2
push offset format_string
call _printf
add esp, 12

但是,我们仍然无法推断eaxedx的值填充了哪个订单cc++