我使用函数fork(),exec()…
但是如何在不包含一些额外的头文件的情况下编译这个程序(比如sys / types.h,sys / wait.h)。
我用ubuntu 10.04和gcc版本4.4.3
#include <stdio.h> #include <stdlib.h> int main() { pid_t pid; printf("before fork\n"); pid = fork(); if(pid == 0) { /*child*/ if(execvp("./cpuid", NULL)) { printf("error\n"); exit(0); } } else { if(wait(NULL) != -1) { printf("ok\n"); } } return 0; }
在传统的“ANSI”C语言中,如果你调用一个没有声明它的函数,那么编译器的行为就好像这个函数被隐式地声明为一个固定但未指定数量的参数并返回int
。 所以你的代码就像fork()
和execvp()
声明一样:
int fork(); int execvp();
由于execvp()
接受固定数量的参数并返回int
,所以这个声明是兼容的。 fork()
也需要固定数量的参数,但返回pid_t
; 但是由于pid_t
和int
在大多数Linux体系结构上是等效的类型,所以这个声明也是有效兼容的。
这些函数的实际定义在C标准库中,它是默认链接的,所以定义在链接时可用,因此代码工作。
正如Keith Thompson所指出的那样,这种语言特性在C语言标准的C99版本中被放弃了,并且在C99或C11模式下调用的编译器必须至少在调用一个函数而不被明确声明的时候发出警告。
exec和fork是在unistd.h中声明的,如果你在你的代码中明确指定了stdio.h或stdlib.h,那么它最有可能包含在其中。 “wait”来自sys / wait.h,尽管…尝试使用-c -E调用gcc来生成预处理的输出,并查看函数的声明来自哪里。
咖啡的答案只是部分正确的。
根据C89 / C90标准(通常称为“ANSI C”)规定的规则,对不具有可见声明的函数的调用是合法的。 编译器假定函数返回一个int
结果,并在调用中给出(提升的)类型的参数。 如果调用与函数定义不一致,则行为是不确定的。 对于这样的通话,完全是程序员的责任, 编译器可能不会告诉你,如果你犯了一个错误。
1999年的ISO C标准放弃了这个“隐含的int
”规则,并且对一个未声明函数的调用违反了约束条件 ,需要进行诊断。 (诊断可能是非致命的警告,也可能导致编译失败。)一旦打印完诊断,如果编译器创建可执行文件,则其行为是不确定的。
不幸的是,许多编译器仍然默认不执行现代C规则。 他们中的大多数可以通过适当的编译时间选项来完成。
特别是对于gcc,你可以编译
gcc -std=c99 -pedantic
要么
gcc -std=c11 -pedantic
(当caf的答案被写入时,后者还不存在)。或者,如果您还想使用gcc特定的扩展,则可以使用-std=gnu99
或-std=gnu11
。 默认是-std=gnu89
。 在将来的gcc版本中,这可能会更改为-std=gnu11
。
gcc兼容的编译器如clang通常会遵循相同的规则。 对于其他编译器,你将不得不咨询他们的文档,以找出如何说服他们执行现代C规则。 (微软的C编译器比C90对于标准的支持非常不全面。)