我有一个类似下面的打印声明......
int i=0;
printf("%d,%d,%d,%d,%d,%d",i++,i,++i,i--,++i,i);
根据优先级i++,i,++i,i--,++i,i
应该像下面一步一步评估......
0,i,++i,i--,++i,i // after this i=1;
0,i,++i,1,++i,i // after this i=0;
0,i,++i,1,1,i // after this i=1;
0,i,2,1,1,i // after this i=2;
0,2,2,1,1,2 // after this i=2;
和最终结果,我认为从这个逻辑应该是......
0,2,2,1,1,2
但我得到了2,2,2,1,2,2
这背后的原因是什么?
顺便说一句,我正在使用visual c ++ 2010 ...
答案 0 :(得分:8)
未定义的行为。 C和C ++语言标准特别保留了函数参数的评估顺序未指定,以便让编译器在各种硬件上生成最优的机器代码。
您不允许在序列点之间多次修改变量。语言标准说序列点只出现在代码中的特定点,例如分隔语句的分号。在初始赋值int i=0;
之后有一个序列点,在printf
返回后有一个序列点,并且在printf
的所有参数都已经过评估之后有一个序列点printf
实际上被调用了,但在每个参数的评估之间都有不的序列点。
答案 1 :(得分:2)
不。
这里的逗号运算符:
a,b;
和分隔函数参数的逗号:
f(a,b);
是不同的。
只有真正的逗号运算符才是序列点,并且会在左边和右边的参数(a
和b
表达式中)对它进行排序评估。
函数参数之间的逗号不是序列点,参数评估的顺序是未定义的(即使是相同的编译器也可能在不同的调用站点中以不同的顺序对它们进行评估)。此外,在序列点之间的程序部分中更改相同的左值(示例中的i
变量)两次或更多次是非法的(未定义的行为)。同一对象的每个修改必须由序列点(例如;
)与同一对象的另一个修改分开。
答案 2 :(得分:1)
您的案例中的逗号不是,
运算符,它依次保证评估,但属于函数调用语法,并且未定义函数参数的计算顺序。因此,您的代码肯定会表现出未定义的行为(它看起来确实如此)。
答案 3 :(得分:0)
由编译器决定它生成的代码。未定义函数调用的参数的评估顺序。