scu*_*zz0 6 c function function-prototypes
我正在学习 C,我的书解释了如何“构建函数原型”,以便我们可以在定义它之前使用它。
关键是我无法想象在定义函数之前需要使用它的情况,为什么我们不能在一开始就定义它呢?
您能否提供一个示例,其中严格需要对函数进行原型设计(如果存在)?
考虑下面的程序:
#include <stdio.h>
void add(int, int);
int main() {
add(5, 3);
return 0;
}
void add(int a, int b) {
printf("%d", a+b);
}
Run Code Online (Sandbox Code Playgroud)
在这里,当您调用add(5, 3)
from时main()
,编译器知道它add()
是什么 - 它接受的参数和返回类型,这要归功于void add(int, int)
第 3 行中的语句。如果该语句被注释掉,那么编译器将不知道是什么add()
并且会给您一个错误。因此,第 3 行告诉编译器您add()
稍后已经定义了该函数,这使得它完全可以在main()
. 或者,如果您在 之前add()
编写函数,那么编译器知道您调用它时的内容;因此在这种情况下不需要函数原型。 main()
add()
希望这有用。
一个用例是当您想要将函数指针指向另一个源文件中定义的函数时。(或者用asm手写)。使用函数指针总是需要提前声明该函数,无论是通过定义还是原型。
C89(及更早版本)允许隐式声明函数(即使编译单元中早期没有定义或原型(this .c + 任何你的东西#include
)也可以使用它们。
因此,您可以在 C89 中将其单独编译到一个文件中(或者在 C99 / C11 模式下大多数编译器发出警告)
int foo() {
return bar( 123 ); /* implicit declaration of int bar() */
}
Run Code Online (Sandbox Code Playgroud)
但不能用作&bar
函数指针
/* int bar(int); necessary if you haven't defined int bar(int x) { ... } */
void *take_fptr() {
return &bar; // error: 'bar' undeclared from GCC
}
Run Code Online (Sandbox Code Playgroud)
您还可以构建需要声明才能正确传递参数的情况,例如,如果您希望函数采用参数float
,则需要通过定义或原型来声明它。当将 arg 传递给非原型函数或可变参数函数(如 printf)的一部分时,ISO C 标准中的“默认参数提升”将提升float
为。double
...
(这就是为什么%f
打印双精度数,而不是浮点数,以及为什么%lf
如果完全支持的话也是双精度数。也是为什么像这样的函数putchar(int)
将它们的 char arg 作为 int:窄整数类型的默认提升到int
。C 标准的某些部分库的历史可以追溯到很早期的 C,在语言支持原型之前!)
或者例如,如果您的函数需要 a long long
,但调用者写入bar( 123 )
,则调用者只会推断int
,其传递方式可能与 a 不同long long
。但你可以通过写来解决这个问题bar( 123LL )
,或者bar( (long long)123 )
或者,如果返回类型不是int
(或void
),那么您还需要编译器通过声明了解该函数。隐式声明的函数假定返回int
。根据调用约定和体系结构,您可能会忽略返回short
类型,或者在某些机器上甚至是char*
,例如在 32 位机器上,intptr_t
其中int
。(早期的 C 就依赖于此。)
但一般来说,例如在具有 64 位指针的机器上,隐式 int 返回将不起作用。它也不适用于double
返回值或struct
.