我正在学习C,我的书正在解释如何“原型化一个函数”,所以我们可以在定义它之前使用它。
关键是我无法想象在定义它之前需要使用函数的情况,为什么我们不能在开始时定义它?
您能否提供一个示例,其中对于函数原型(如果存在)是非常必要的?
答案 0 :(得分:1)
考虑以下计划:
#include <stdio.h>
void add(int, int);
int main() {
add(5, 3);
return 0;
}
void add(int a, int b) {
printf("%d", a+b);
}
在这里,当您从add(5, 3)
调用main()
时,编译器知道add()
是什么 - 它所采用的参数和返回类型,这要归功于void add(int, int)
中的语句{第3行。如果这个语句被注释掉,那么编译器将不知道add()
是什么并且会给你一个错误。因此,第3行告诉编译器您之后已经定义了函数add()
,这使得它完全有资格在main()
中使用。或者,如果您在 add()
之前编写main()
函数,则编译器会在调用它时知道add()
是什么;所以在这种情况下不需要函数原型。
希望这很有用。
答案 1 :(得分:1)
一个用例是当您希望将函数指针指向另一个源文件中定义的函数。 (或用 asm 手写)。获取函数指针总是需要通过定义或原型提前声明该函数。
C89(及更早版本)允许隐式声明函数(即使编译单元中没有定义或原型,也可以使用它们(这个 .c + 任何你 #include
)。
所以你可以在 C89(或 with a warning from most compilers in C99 / C11 mode)中自己编译一个文件
int foo() {
return bar( 123 ); /* implicit declaration of int bar() */
}
但是你不能使用 &bar
作为函数指针
/* int bar(int); necessary if you haven't defined int bar(int x) { ... } */
void *take_fptr() {
return &bar; // error: 'bar' undeclared from GCC
}
您还可以构建需要声明才能正确传递参数的情况,例如如果您希望函数采用 float
参数,则需要通过定义或原型对其进行声明。 ISO C 标准中的“默认参数提升”将在将 arg 传递给非原型函数时将 float
提升为 double
,或者将参数传递给 printf 等可变参数函数的 ...
部分。< /p>
(这就是为什么 %f
打印双精度数而不是浮点数的原因,以及为什么 %lf
如果完全支持它也是双精度数。也是为什么像 putchar(int)
这样的函数将它们的 char arg 作为一个 int:窄整数类型的默认提升到 int
。C 标准库的某些部分可以追溯到非常早期的 C,在语言支持原型之前!)
或者例如,如果您的函数需要一个 long long
,但调用者写的是 bar( 123 )
,则调用者只会推断出 int
,它的传递方式可能与 {{1} }}。但是您可以通过编写 long long
或 bar( 123LL )
或者如果返回类型不是bar( (long long)123 )
(或int
),那么您还需要编译器通过声明来了解该函数。假定隐式声明的函数返回 void
。根据调用约定和架构,对于 int
返回类型,或者在某些机器上,甚至对于 short
,您可能会避开它,例如在 char*
为 intptr_t
的 32 位机器上。 (早期的 C 依赖于此。)
但总的来说,例如在具有 64 位指针的机器上,implicit-int return 不起作用。它也不适用于 int
返回值或 double
。
答案 2 :(得分:-1)
当时可能不知道该功能的定义。想象一个调用malloc
来分配内存的程序。在编译时,没有人知道程序将在运行时使用什么分配器。那你怎么定义这个功能呢?