评估报表

//prog1.c #include  int f(int *a,int *b,int c) { if(c == 0) return 1; else { *a = *a + 1; *b = *b - 1; c = c - 1; return (*a + f(a,b,c) + *b); } } int main() { int a = 3,b = 3,c = 3; printf("%d\n",f(&a,&b,c)); return 0; } 

我使用gccclang-3.5执行程序,发现输出= 16

我认为可能存在一些特定于实现的行为,如下面的代码

 //prog2.c #include  int f(int *x,int *y,int *z) { *x = *x + 1; *y = *y + 1; *z = *z + 1; return 0; } int main() { int a=0,b=0,c=0; printf("%d %d %d\n",a,f(&a,&b,&c),b);; return 0; } // gcc output : 1 0 0 // clang-3.5 : 0 0 1 

prog1.c中, return语句中是否存在任何特定于实现的行为? 如果不是如何评估?

我可能不知道某种undefined behaviour unspecified behaviour 。 请解释。 谢谢

正如评论中和近似重复的问题中所述( C中是否存在未定义的行为?如果不是,则逻辑地预测输出。 ),这两个程序的结果并未完全由C标准定义 – 它们产生’未指定的行为’,因为第一个的return语句和第二个中的printf()调用中的术语的评估顺序不是由语言指定的,而是编译器的奇思妙想。 (请注意,它是’未指定的行为’而不是正式’未定义的行为’ – 请参阅注释中的讨论。它也不是’实现定义’行为;不需要实现来记录它的作用。)

这意味着任何实现给出的结果都是问题方面的“特定于实现”。 不同的实现可以合法地产生不同的答案。

第一个项目是:

 #include  int f(int *a,int *b,int c) { if(c == 0) return 1; else { *a = *a + 1; *b = *b - 1; c = c - 1; return (*a + f(a,b,c) + *b); } } int main() { int a = 3,b = 3,c = 3; printf("%d\n",f(&a,&b,c)); return 0; } 

有问题的部分是return (*a + f(a,b,c) + *b); 因为*a可以在递归函数调用之前或之后进行求值,而f()修改ab指向的值,因此评估顺序很重要。 不同的编译器可以合法地产生不同的结果。 相同的编译器可以在不同的时间,或在不同的优化标志下或根据其选择产生不同的结果。 *a*b都可以在调用之前或者在调用之后进行评估,或者可以在之前和之后评估其中任何一个 – 并且只列出4个合理的替代方案。

第二个方案是:

 #include  int f(int *x,int *y,int *z) { *x = *x + 1; *y = *y + 1; *z = *z + 1; return 0; } int main() { int a=0,b=0,c=0; printf("%d %d %d\n",a,f(&a,&b,&c),b);; return 0; } 

问题是标准没有指定af(&a, &b, &c)bprintf()调用求值的顺序,并且根据编译器选择的顺序得到不同的结果。 你表明GCC和Clang产生了不同的结果 – 根据标准,这些结果都是可以接受的,其他很多都是如此。

在prog1.c中,return语句中是否存在任何特定于实现的行为? 如果不是如何评估?

return语句没有任何问题,除非你用c调用f的原始调用是否定的,递归调用将是无穷无尽的。

你的函数f的用途并不清楚 – 但终止条件应更好地写成:

 if(c <= 0) return 1;