我一直试图理解printf如何处理传递给它的参数。更具体的是,有人可以解释以下输出是如何产生的。
int a=1;
printf("%d %d %d",++a,a,a++);// outputs: 3 3 1
a=1;
printf("%d %d %d",a++,a,a++);// outputs: 2 3 1
a=1;
printf("%d %d %d",a,a,a++);// outputs: 2 2 1
a=1;
printf("%d %d %d",a,a++,a);// outputs: 2 1 2
a=1;
printf("%d %d %d",a,a,++a);// outputs: 2 2 2
cout
语句会产生相同的输出。
答案 0 :(得分:4)
此代码
printf("%d %d %d",++a,a,a++);// outputs: 3 3 1
在同一个表达式中修改两次。确切地说,它修改了两次而没有插入序列点。因此,此代码具有未定义的行为,任何推理它的尝试都是徒劳的。编译器可以做它想做的事情,不同的编译器会做不同的事情。有关详细说明,请参阅undefined behavior and sequence points。
使用这样的代码
printf("%d %d %d",a,a,a++);// outputs: 2 2 1
当++增加时,它确实是未定义的,它可以在a用于其他参数之前或之后。所以你的输出可能会有所不同。
唯一真正理解的是不要写这样的代码。遵循这条规则,你不会出错。
答案 1 :(得分:2)
这与printf
和cout
的工作方式无关。 C ++标准定义了表达式评估及其副作用的排序。 C ++ 03和C ++ 11之间的措辞有所改变,但它目前将函数参数的评估描述为 unsequenced 。也就是说,您无法保证将执行函数参数的顺序。
由于您在两个未经过排序的表达式中使用a
的值并修改a
,因此您有未定义的行为。
如果对标量对象的副作用相对于对同一标量对象的其他效果或使用相同标量对象的值进行的值计算未进行排序,则行为未定义。