我想做类似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 ++”语句的位置进行更改。
答案 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
但是,我们仍然无法推断eax
和edx
的值填充了哪个订单c
和c++
。