2

我有一个很小的代码,但我不明白为什么输出是这样的。
这里是

#include <stdio.h>

int f(int i, int j, int k);

int main(int argc, char const *argv[])  
{  
    int a;   
    printf("enter a\n");  
    scanf("%d",&a);  
    f(a,a++,a++);  
    printf("%d \n",a );  
    return 0;  
}  

int f(int i, int j, int k)  
{  
    printf("function arguments \n");  
    printf("%d %d %d\n",i,j,k );  
}   

输入:4
输出:6 5 4

4

2 回答 2

4

标记副本中接受的答案是不正确的。


f(a,a++,a++); 

导致未定义的行为。它试图在a没有中间序列点的情况下修改参数。此外,重要的是要注意函数参数的评估顺序是Unspecified。有可能:

  • 从左到右或
  • 从右到左或
  • 编译器选择的任何神奇顺序。

如果您使用的是 GCC,您可以使用警告标志-wsequence-point来警告您与序列点相关的未定义行为。


在 GCC 中,如果您以最严格的警告级别编译程序,编译器将为您提供以下诊断:

prog.c:10:18: 错误: 'a' 上的操作可能未定义 [-Werror=sequence-point]
prog.c:10:18: 错误: 'a' 上的操作可能未定义 [-Werror=sequence-观点]


参考:

C99 标准 §6.5.2.2:
第 10 段:

函数指示符、实际参数和实际参数中的子表达式的求值顺序未指定,但在实际调用之前有一个顺序点。

请注意,引用仅表示在实际函数调用之前有一个序列点,并不意味着在子表达式参数的评估之间有一个序列点。

于 2013-02-22T15:22:10.147 回答
1

f(a,a++,a++);似乎是未定义的行为,因为:

如果标量对象上的副作用相对于同一标量对象上的不同副作用或使用相同标量对象的值的值计算是未排序的,则行为未定义。如果一个表达式的子表达式有多个允许的排序,则如果在任何排序中出现这种未排序的副作用,则行为是未定义的。

当您使用未定义的行为时,C 标准没有要求。

于 2013-02-22T15:22:55.623 回答