当前位置:  开发笔记 > 运维 > 正文

即使我们不在C程序中包含stdio.h,为什么我们不会得到编译时错误?

如何解决《即使我们不在C程序中包含stdio.h,为什么我们不会得到编译时错误?》经验,为你挑选了2个好方法。

当我首先没有包含任何头文件时,编译器如何知道sleep函数的原型甚至printf函数?

此外,如果我指定sleep(1,1,"xyz")或任意数量的参数,编译器仍然编译它.但奇怪的是gcc能够在链接时找到这个函数的定义,我不明白这是怎么可能的,因为实际sleep()函数只接受一个参数,但是我们的程序提到了三个参数.

/********************************/
int main()
{
 short int i;
 for(i = 0; i<5; i++)
 {
    printf("%d",i);`print("code sample");`
    sleep(1);
 }
 return 0;
}

DGentry.. 10

缺少更具体的原型,编译器将假定函数返回int并获取您提供的任意数量的参数.

根据CPU体系结构,参数可以在寄存器中传递(例如,MIPS上的a0到a3),或者像在原始x86调用约定中一样将它们推送到堆栈中.在任何一种情况下,传递额外的参数都是无害的.被调用的函数不会使用传入的寄存器,也不会引用堆栈上的额外参数,但没有什么不好的事情发生.

传递更少的参数更成问题.被调用的函数将使用发生在适当的寄存器或堆栈位置的任何垃圾,并且可能随之发生hijinks.



1> DGentry..:

缺少更具体的原型,编译器将假定函数返回int并获取您提供的任意数量的参数.

根据CPU体系结构,参数可以在寄存器中传递(例如,MIPS上的a0到a3),或者像在原始x86调用约定中一样将它们推送到堆栈中.在任何一种情况下,传递额外的参数都是无害的.被调用的函数不会使用传入的寄存器,也不会引用堆栈上的额外参数,但没有什么不好的事情发生.

传递更少的参数更成问题.被调用的函数将使用发生在适当的寄存器或堆栈位置的任何垃圾,并且可能随之发生hijinks.



2> Ben Combee..:

在经典C中,您不需要原型来调用函数.编译器将推断该函数返回一个int并获取未知数量的参数.这可能适用于某些体系结构,但如果函数返回int之外的其他内容(如结构)或者有任何参数转换,它将失败.

在您的示例中,可以看到睡眠,编译器会假设原型为

int sleep();

请注意,参数列表为空.在C中,这与void不同.这实际上意味着"未知".如果你正在编写K&R C代码,你可以通过代码来获得未知参数

int sleep(t)
int t;
{
   /* do something with t */
}

这一切都很危险,特别是在一些嵌入式芯片上,其中为非原型函数传递参数的方式与原型不同.

注意:链接不需要原型.通常,链接器会自动链接到Linux上的glibc之类的C运行时库.您使用sleep和实现它的代码之间的关联发生在源代码处理很久之后的链接时间.

我建议您使用编译器的功能来要求原型以避免这样的问题.使用GCC,它是-Wstrict-prototypes命令行参数.在CodeWarrior工具中,它是C/C++编译器面板中的"Require Prototypes"标志.

推荐阅读
雯颜哥_135
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有