在printf中解释评估顺序

可能重复:
C函数调用之前的参数评估顺序

main() { int i=5; printf("%d%d%d%d%d%d",i++,i--,++i,--i,i); } 

输出是45545,但我不知道它是如何工作的。 有人说函数调用中的参数是从左到右推入堆栈的。

函数parameter passing的顺序没有在标准中定义,而是由编译器使用的调用约定决定的。 我认为在你的情况下,使用cdecl调用约定(许多C编译器用于x86架构),函数中的参数从右向左评估。

function参数的评估顺序是未指定的。

从c99标准:

6.5.2.2函数调用

10 /实际参数中函数指示符的评估顺序,实际参数和子expression式是未指定的,但在实际调用之前有一个顺序点。

但是,这只是问题的一部分。 另一件事(实际上更糟,因为它涉及未定义的行为)是:

6.5expression式

2 /在前一个和下一个序列点之间,一个对象应该通过评估一个expression式来最多修改一次对象的存储值。 此外,先前的值应该是只读的,以确定要存储的值。

在我们的例子中,所有的参数评估只在两个序列点之间:前一个; 和input函数之前的点,但所有的参数已被评估。 你最好不要写这样的代码。

C标准在一些地方相当放松,为编译器可能做的优化留下空间。

printf参数的评估顺序是未指定的。 这取决于您正在使用的系统的调用惯例。 此外,这也是一个未定义的行为,因为你正在修改i几次没有任何顺序点。 顺便说一句,有一个失踪的论点。

这个函数调用是未定义的行为:

 printf("%d%d%d%d%d%d",i++,i--,++i,--i,i); 

在两个序列点之间多次修改一个对象在C中是未定义的行为

这也是未定义的行为,因为你有6个转换规范,但格式只有5个参数。

两点:

  • 函数参数以未定义的顺序进行评估。 这使编译器可以优化,但它喜欢。
  • 您的特定参数调用未定义的行为。 在序列点之前,您不允许多次修改i