先前的函数声明
为什么 C 语言中需要预先声明函数?
Why do functions need to be prior declared in C ?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
为什么 C 语言中需要预先声明函数?
Why do functions need to be prior declared in C ?
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
接受
或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
发布评论
评论(6)
现代 C 语言中的函数需要预先声明,原因有两个:1)告诉编译器特定名称是函数的名称(而不是其他名称),2)告诉编译器确切的返回类型函数,以便编译器可以正确处理该返回。
在 C 中,可以使用或不使用原型来声明函数。原型声明为编译器提供了更多信息。它包括有关函数参数(如果有)的数量和类型的信息,从而帮助编译器正确准备函数调用的参数。
在 C 语言的 C89/90 版本中,函数不必事先声明,这导致编译器在调用时对函数做出假设。不用说,在许多情况下这被证明是危险的。
Functions in modern C language need to be prior-declared for two reasons: 1) to tell the compiler that a specific name is the name of a function (and not of something else), 2) to tell the compiler the exact return type of the function so that the compiler can handle that return correctly.
In C a function can be declared with or without prototype. A prototype declaration provides more information to the compiler. It includes information about the number and the types of function parameters (if any), thus helping the compiler to prepare the arguments for the function call properly.
In C89/90 version of C language the functions didn't have to be prior declared, which resulted in the compiler making assumptions about the function at the point of the call. Needless to say, in many cases this proved to be dangerous.
这样编译器就能够在调用函数时检测到类型错误。当然有很多方法可以解决这个问题,但这就是他们选择的方式。
So that the compiler will be able to detect type errors when you call functions. Of course there are ways around that, but that's the way they chose.
这样一次性编译器就知道要为每个参数传递多少字节。
考虑一下:
如果没有原型,编译器将假设
f
接受整数,并将sizeof(int)
字节发送到函数(通过堆栈或寄存器,具体取决于平台) 。但该函数只会查看 1 个字节,这会给出错误的结果。So that the one-pass compiler knows how many bytes to pass for each argument.
Consider:
Without a prototype, the compiler will assume that
f
accepts ints, and sendsizeof(int)
bytes to the function (through stack or registers, depending on the platform). But the function will only look at 1 byte, which will give the wrong result.因为旧的编译器速度和内存有限,所以他们希望一切都可以一次性完成(只需从上到下读取文件,一切就都可以理解)。
现代设计的编译器可以向上、向下查找函数,甚至在尚未声明的不同文件中查找函数。
Because old compilers have limited speed and memory, so they want everything can be done in one pass (just read the file from top to bottom and everything is understood).
Modern-designed compilers can look for functions up, down, even in different files when it is not yet declared at a point.
基本上,你不......
很多编译器会假设你正在调用 int Function() 签名,如果你还没有声明它。链接器......嗯......可能不会吃那个。
如果声明的函数的签名与调用语句不匹配,编译器会介意,但第二步就会出现问题:
- 参数传递和返回值预编码的编码
后者实际上必须为每次调用确定。正是在第二个代码生成步骤中,C 编译器真正错过了声明(这就是函数签名的原因)。
然后链接器还需要将函数的符号调用转换为实际的...呃...调用。但是,如果该函数存在于“某处”(去研究extern修饰符),链接器将不会成为一个显示障碍。
所有这一切的例外是函数指针机制,您可以在其中告诉编译器和链接器预期的签名,但调用本身不是由编译器决定的,链接器也没有“硬编码”调用...检查它出来了。
Basically, you don't....
A lot of compilers will assume you're calling a int Function() signature, if you haven't declared it yet. The linker... hmmm.. will probably not eat that.
The compiler will mind if the signature of the declared Functions doesn't match the calling statement, but it is at a second step where things go wrong:
- coding for argument passing and return value pre-code
The latter actually has to be determined for each calling. It's at this second code-generation step that C compiler really misses the declaration (which is what makes a function signature).
Then the linker also needs to turn symbolic calls of functions into actual... er... calls. But if the function exists "somewhere" (go investigate the extern modifier), the linker won't be a show stopper.
The exception to all this is the function pointer mechanism, where you tell the compiler and linker the signature to be expected, but the call itself is not decided by the compiler , neither you have a "hardcoded" call by the linker... check it out.
我确信这不是唯一的原因,但是当您只知道函数的声明(例如来自头文件)时,您可以编译包含对其他函数的调用的文件。这是可能的,无需重新编译函数本身的定义(可能位于另一个文件中)。但为了验证函数是否被正确调用,编译器必须知道它的声明。然后链接器将处理剩下的事情。
这里有一个小例子
main.c:
function.h:
function.c:
我正在使用 gcc 进行编译:
这将生成一个目标文件 function.o。现在,当我想编译我的主函数时,我不必再编译我的 function.c 文件,我只需要知道头文件和目标文件中的声明:
现在,目标文件将链接到我的程序无需重新编译。
I am sure this is not the only reason, but you can compile files with calls to other functions when you only know the declaration of the function for example from a header file. This is possible without recompiling the definition of the function itself (which might be in another file). But to verify the function is called correctly, the compiler has to know its declaration. Then the linker will take care of the rest.
Here a little example
main.c:
function.h:
function.c:
I am using gcc to compile like that:
this will produce an object file function.o. Now, when I want to compile my main function, I don't have to compile my function.c file anymore, I only have to know the declaration from the header file and the object file:
Now, the object file will get linked into my program without recompiling.