int main(){
int scanf(), printf(), atoi(int x), atol(int x);
//int scan();
int a=5;
scanf();
printf();
atoi(a);
atol(a);
//scan();
return 0;
}
如果使用带-Wall选项的gcc 4.9.2编译上述代码,则会得到以下输出:
gcc 1.c -Wall -o 1.out
1.c: In function ‘main’:
1.c:3:6: warning: conflicting types for built-in function ‘scanf’
int scanf(),printf(),atoi(int x),atol(int x);
^
1.c:3:14: warning: conflicting types for built-in function ‘printf’
int scanf(),printf(),atoi(int x),atol(int x);
^
程序被编译,没有链接器错误。但是,执行它会使程序因Segmentation Fault而崩溃。有趣的是,只有标准的库函数名称才有可能。如果您尝试使用扫描等任意函数名编译和链接程序,链接器会抛出一个错误,指出“未定义的扫描引用”。
gcc发生了什么事?
(抱歉格式不佳。我是StackOverflow的新手。)
答案 0 :(得分:1)
链接器不强制链接的函数具有正确的原型。它只是链接到具有指定名称的函数。您使用不正确的原型声明函数。因此运行时错误。
必须使用正确的原型声明外部函数。包括相应的头文件来执行此操作。
答案 1 :(得分:0)
好吧,听起来你的问题确实与找到函数的原因有关,尽管没有包含头文件。所有头文件都是告诉编译器有关参数类型和函数的返回值。使用该信息,编译器能够为调用这些函数生成正确的代码,并根据需要生成警告和错误。但最终,您只需在目标文件中使用外部符号引用。这些引用期望外部定义的实体具有这些名称。
编译后,将目标文件与任何所需的库组合在一起,以生成可执行程序。此阶段称为链接。链接时,有一个搜索的默认库路径,您可以使用库选项向其添加库(例如,如果您引用math.h
中定义的函数,则在链接选项中包含-lm
,至少在Unix系统上。)
因此,如果您未能在源代码中声明一个函数,它将被隐式声明为返回int
并采用未指定的参数。如果您明确错误地声明了某个函数,则结果类似。在链接期间,链接器仍将从库中找到该函数,就像您已包含头文件一样。它对链接器没有任何影响。但生成的代码可能不正确,不应该运行。
包含头文件不会影响链接期间搜索的库。
这会回答这个问题吗?