0

我想知道,如果我有这样的源文件

#include <stdio.h>
int main()
{
   printf("Hello world");
}

据我所知,头文件只包含函数的原型。如果是这样,我的源文件如何获得函数 printf ?如果我不包含已声明的源文件?谢谢你

4

5 回答 5

3

问题尚不清楚,但在创建程序之前会发生两件事,

  1. 编译(需要原型/声明)

  2. 链接(需要定义)。

了解原型需要标头信息。即使这样编译也很好:

int printf ( const char * format, ... );
int main()
{
   printf("Hello world");
}

在链接时不会有任何问题,因为该printf函数是在 C 标准库中找到的,因此在链接时它将查看标准目录(保存库的编译器的 bin/lib 文件夹)并链接该函数。

源只需要知道原型。在这种情况下,程序员会遇到的问题:

int my_printf ( const char * format, ... );
int main()
{
   my_printf("Hello world");
}

上面会编译,但是在链接my_printf你的代码时没有定义,所以它会在链接时出错。

于 2013-10-28T07:09:50.887 回答
2

头文件具有函数的定义声明(stdio.h具有定义声明printf)。实际函数存在于库中,并在编译代码时被链接。

于 2013-10-28T07:07:14.480 回答
0

在使用库时,您在代码中包含库的标头,并指示链接器使用该库的代码文件(通常是目标文件)进行链接。对于标准库,IDE 通常会指示链接器默认链接到它们。

于 2013-10-28T07:08:11.817 回答
0

假设您使用 gcc 作为编译器,标准库默认链接,这就是函数定义所在的位置。如果您想确切查看正在链接的库,您可以传递 gcc 的 -v 选项,这将导致它转储有关它将使用的默认选项的信息,包括库路径和默认库以及将链接的目标文件.

如果您提供 -Wl,--verbose 选项,gcc 会将 --verbose 传递给链接器,链接器将准确转储它正在寻找库的位置,包括失败和成功的搜索

gcc -v foo.c -Wl,--verbose

于 2013-10-28T07:19:56.577 回答
0

头文件stdio.h将声明printfextern函数,即,它在别处定义。只要您使用的函数有声明,编译器就会很高兴。链接器是解决这些依赖关系的一个。

当您开始提出这样的好问题时,一件非常有用的事情是使用一些链接器命令。

假设你在 *nix 上,一旦你有你的可执行文件(让我们称之为foo),做:

ldd foo

您应该会看到创建时链接的库列表foo

libc.so应该是其中之一。它包含printf除其他外的定义!

您可以参考链接了解更多信息

于 2013-10-28T07:21:35.417 回答