未定义的函数已编译和链接

时间:2015-12-20 08:40:52

标签: c gcc

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的新手。)

2 个答案:

答案 0 :(得分:1)

链接器不强制链接的函数具有正确的原型。它只是链接到具有指定名称的函数。您使用不正确的原型声明函数。因此运行时错误。

必须使用正确的原型声明外部函数。包括相应的头文件来执行此操作。

答案 1 :(得分:0)

好吧,听起来你的问题确实与找到函数的原因有关,尽管没有包含头文件。所有头文件都是告诉编译器有关参数类型和函数的返回值。使用该信息,编译器能够为调用这些函数生成正确的代码,并根据需要生成警告和错误。但最终,您只需在目标文件中使用外部符号引用。这些引用期望外部定义的实体具有这些名称。

编译后,将目标文件与任何所需的库组合在一起,以生成可执行程序。此阶段称为链接。链接时,有一个搜索的默认库路径,您可以使用库选项向其添加库(例如,如果您引用math.h中定义的函数,则在链接选项中包含-lm,至少在Unix系统上。)

因此,如果您未能在源代码中声明一个函数,它将被隐式声明为返回int并采用未指定的参数。如果您明确错误地声明了某个函数,则结果类似。在链接期间,链接器仍将从库中找到该函数,就像您已包含头文件一样。它对链接器没有任何影响。但生成的代码可能不正确,不应该运行。

包含头文件不会影响链接期间搜索的库。

这会回答这个问题吗?