C中函数调用的后缀或前缀增量的未定义行为

我在这个网站上看到,函数调用中的前缀增量或后缀增量可能会导致未定义的行为。 我最近经历过其中一个。 源代码是这样的:

#include  void call(int,int,int); int main() { int a=10; call(a,a++,++a); printf("****%d %d %d***_\n",a,a++,++a); return 0; } void call(int x,int y,int z) { printf("%d %d %d",x,y,z); } 

输出结果为12 11 12 **** 14 13 14 *** _。 但是,当a在函数中首先打印时,它不应该是10吗? 它为什么变成12? 另外,为什么++从12减少到11? 有人可以请解释一下吗? 谢谢。

这是未定义的行为,因此完全取决于编译器的实现,其中以下操作的顺序如下:

  1. 提交参数a
  2. 提交参数a++
  3. 提交参数++a
  4. 增加a for ++a
  5. a++增加a

编译器唯一知道的是:2。必须在5之前发生,4。必须在3之前发生。

你在观察:

 ++a; submit argument 2 a++; submit the other arguments 

您的示例代码需要我们考虑两件事:

  1. 未指定评估的函数参数顺序。 因此,首先评估++aa++但它依赖于实现。

  2. 在修改之间没有序列点的情况下修改多次的值也是未定义的行为。

由于第2点,你在这里有两个未定义的行为(你做了两次)。 注意未定义的行为并不意味着没有任何反应; 这意味着一切都会发生。

 call(a,a++,++a); /* UB 1 */ printf("****%d %d %d***_\n",a,a++,++a); /* UB 2 */ 

C和C ++标准不表示函数参数的评估顺序。 简而言之,编译器从右到左或从左到右计算参数并不是不正确的。

最好的答案是, 远离这种“未定义的行为”; 因为它可能导致微妙的可移植性问题。

没有要求等于任何东西 ; 这就是未定义行为的含义。 完全取决于编译器以其认为合适的任何顺序评估callprintf的参数,因为该语言没有指定需要评估的顺序。