//prog1.c
#include <stdio.h>
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;
}
我使用gcc
和clang-3.5
执行了该计划,并找到了输出= 16
。
我认为可能存在一些特定于实现的行为,如下面的代码
//prog2.c
#include <stdio.h>
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
。请解释。
感谢
答案 0 :(得分:2)
正如评论和近似重复的问题(Is this undefined behaviour in C? If not, predict the output logically.)所述,这两个程序的结果并未完全由C标准定义 - 它们产生'未指明的行为',因为这些术语的评估顺序在第一个return
语句中,第二个printf()
调用不是由语言指定的,而是编译器的一时兴起。 (请注意,它是'未指定的行为',而不是正式'未定义的行为' - 请参阅注释中的讨论。它也不是'实现定义'行为;不需要实现来记录它的作用。)
这意味着任何实现给出的结果都是问题条款中的“特定于实现”。不同的实现可能合法地产生不同的答案。
第一个项目是:
#include <stdio.h>
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()
修改a
和b
的值因此,评估的顺序很重要。不同的编译器可以合法地产生不同的结果。相同的编译器可以在不同的时间,或在不同的优化标志下或根据其选择产生不同的结果。 *a
和*b
都可以在调用之前或者在调用之后进行评估,或者可以在之前和之后评估其中任何一个 - 并且只列出4个合理的替代方案。
第二个程序是:
#include <stdio.h>
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;
}
问题是标准未指定a
,f(&a, &b, &c)
和b
评估printf()
调用的顺序,您会得到不同的结果取决于编译器选择的顺序。你证明了GCC和Clang产生了不同的结果 - 根据标准,这些结果都是可以接受的,其他很多都是可以接受的。
答案 1 :(得分:0)
在prog1.c中,return语句中是否存在任何特定于实现的行为?如果不是如何评估?
return
声明没有任何问题,只是如果您对f
c
的原始电话是否定的,那么递归通话将会无穷无尽。
您的函数f
的目的尚不清楚 - 但终止条件应更好地写为:
if(c <= 0) return 1;