C 请解释prog是如何工作的 #包括 int f(); int main() { f(1); f(1,2); f(1,2,3); } f(整数i,整数j,整数k) { printf(“%d%d%d”,i,j,k); }
它运行良好(没有任何错误)…u plz可以解释它是如何执行的吗?C 请解释prog是如何工作的 #包括 int f(); int main() { f(1); f(1,2); f(1,2,3); } f(整数i,整数j,整数k) { printf(“%d%d%d”,i,j,k); },c,C,它运行良好(没有任何错误)…u plz可以解释它是如何执行的吗? f(1)和f(1,2)如何链接到f(int,int,int)?您必须对“错误”有不同的定义:-)您调用f函数的前两次打印的是什么?我明白了 #include<stdio.h> int f(); int main() { f(1); f(1,2); f(1,2,3); } f(int i,int j,int k) { printf("%d %d %d",i,j,k); } 对于
f(1)和f(1,2)如何链接到f(int,int,int)?您必须对“错误”有不同的定义:-)您调用
f
函数的前两次打印的是什么?我明白了
#include<stdio.h>
int f();
int main()
{
f(1);
f(1,2);
f(1,2,3);
}
f(int i,int j,int k)
{
printf("%d %d %d",i,j,k);
}
对于我的三个函数调用
你看到的是C语言早期的遗留问题,当时人们在函数调用中自由发挥
所发生的一切就是调用一个函数f
,它从堆栈中打印出三个值(是的,即使只给它一个或两个值)。当您没有提供足够的数据时,您的程序很可能只使用已有的数据,通常在读取时会导致数据问题,在写入时会导致灾难性的失败
这是完全可编译的,尽管非常不明智,C。我的意思是,在一个非常真实的“未定义的行为”中,这个词的意思是(特别指C99:“如果表示被调用函数的表达式的类型不包含原型,……如果参数的数量不等于参数的数量,则行为未定义”)
您应该提供完整的函数原型,例如:
1 -1216175936 134513787
1 2 134513787
1 2 3
为了确保编译器能够解决这个问题,请在变量参数函数中使用省略号(…
)
另一方面,通常情况下,调用函数以堆栈开始,如:
void f(int,int,int);
并将(例如)两个值推送到堆栈上,使其最终类似于:
12345678
11111111
当被调用函数使用堆栈上的前三个值时(因为这是它想要的),它会发现它有1
、2
和11111111
它做它必须做的事情,然后返回,调用函数从堆栈中清除这两个值(这称为调用方做好策略).wow betide任何尝试使用被调用方的人都是很好的策略:-)尽管这在C语言中很少见,因为它使得变量参数函数如printf
有点难实现
在C中,它声明了一个函数,该函数接受可变数量的参数,即,它等价于C中的以下函数++
int f();
要检查这一点,请使用以下命令,而不是int f();
这将导致编译器抱怨
请注意:这里还涉及C链接器的一个怪癖…C链接器在调用时不验证传递给函数的参数,只是链接到具有相同名称的第一个公共符号。因此允许在main中使用f(),因为声明了int f()
。但是链接器绑定函数f(int,int,int)在调用站点的链接时间。希望这有意义(如果没有),请告诉我)此声明:
int f(void);
…告诉编译器“f
是一个函数,它接受一些固定数量的参数,并返回int
”。然后尝试使用一个、两个和三个参数调用它-C编译器在概念上是一个过程(预处理后),因此在这一点上,编译器没有可用的信息与您争论
f()的实际实现
接受三个int
参数,因此只提供一个和两个参数的调用调用未定义的行为-这是一个错误,意味着编译器不需要向您提供错误消息,并且在您运行程序时可能发生任何情况。由于int f()
表示其他答案已经说过的:它表示未指定数量的参数。这意味着您可以使用所需数量的参数(也超过3个)调用它,而无需编译器对其进行任何说明
它之所以“隐蔽”工作,是因为参数被推到堆栈上,然后从f
函数中的堆栈“访问”。如果传递0个参数,则函数的i,j,k
对应“到堆栈上的值,从函数PoV来看,这些值是垃圾。尽管如此,您仍然可以访问它们的值。如果您传递1个参数,则三个i j k
中的一个访问该值,其他值则获取垃圾。依此类推
请注意,如果以其他方式传递参数,同样的推理也会起作用,但无论如何,这些都是使用中的约定。这些约定的另一个重要方面是被调用方不负责调整堆栈;由调用方决定推送多少实数参数。如果不是这样,则定义f的的on可能表示它必须“调整”堆栈以“释放”三个整数,这将导致某种崩溃
你所写的对于当前的标准来说很好(在gcc上编译时没有警告,即使使用-std=c99-pedantic
;有一个警告,但它是关于f
定义前面缺少的int
),尽管许多人觉得它很恶心并称之为“过时的特性”.当然,您在示例代码中的用法没有显示出任何用处,而且它可能有助于消除bug—原型的更具约束力的用法!(但是,我还是更喜欢C而不是Ada)
添加
“特性”的更“有用”的用法不会触发“未定义行为”问题,可以是
int f();
#包括
int f();
int main()
{
f(1);
f(2,2);
f(3,2,3);
}
int f(int i,int j,int k)
{
如果(i==1)printf(“%d\n”,i);
如果(i==2)printf(“%d%d\n”,i,j);
如果(i==3)printf(“%d%d%d\n”,i,j,k);
}
使用g++编译器编译同一程序时,您会看到以下错误-
#include<stdio.h>
int f();
int main()
{
f(1);
f(2,2);
f(3,2,3);
}
int f(int i,int j,int k)
{
if ( i == 1 ) printf("%d\n", i);
if ( i == 2 ) printf("%d %d\n", i, j);
if ( i == 3 ) printf("%d %d %d\n", i, j, k);
}
将gcc与选项-std=c99一起使用只会给出一个警告
使用与g++相同的标准编译相同的程序
int f();
#include<stdio.h>
int f();
int main()
{
f(1);
f(2,2);
f(3,2,3);
}
int f(int i,int j,int k)
{
if ( i == 1 ) printf("%d\n", i);
if ( i == 2 ) printf("%d %d\n", i, j);
if ( i == 3 ) printf("%d %d %d\n", i, j, k);
}
g++ program.c
program.c: In function `int main()':
program.c:2: error: too many arguments to function `int f()'
program.c:6: error: at this point in file
program.c:2: error: too many arguments to function `int f()'
program.c:7: error: at this point in file
program.c:2: error: too many arguments to function `int f()'
program.c:8: error: at this point in file
program.c: At global scope:
program.c:12: error: ISO C++ forbids declaration of `f' with no type
gcc program.c -std=c++98
cc1: warning: command line option "-std=c++98" is valid for C++/ObjC++ but not for C
int f();
f(int i,int j,int k)
{
printf("%d %d %d",i,j,k);
}
f(int,int,int); //in your case
f(void); //if you have no parameters