C头文件和编译/链接

Ari*_*des 29 c linker

我知道头文件有各种函数,结构等的前向声明,在.c'调用'的文件中使用#include,对吗?据我了解,"权力分立"的情况如下:

头文件: func.h

C源文件: func.c

C源文件source.c("实际"程序):

#include <stdio.h>
#include "func.h"

int main(void) {
    int res = func(3);
    printf("%i", res);
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:看到它#include只是一个复制文件中的内容的编译器指令,.h文件#include如何.c知道如何实际执行该函数?所有它都是int func(int i);,所以它如何实际执行功能?它如何获得对实际定义的访问func?标题是否包含某种"指针",表示"那是我的定义,那边!"?

它是如何工作的?

Emi*_*tai 29

Uchia Itachi给出了答案.这是链接器.

使用GNU C编译器,gcc您将编译一个单文件程序,如

gcc hello.c -o hello # generating the executable hello
Run Code Online (Sandbox Code Playgroud)

但是,如您的示例中所述编译两个(或更多)文件程序,您必须执行以下操作:

gcc -c func.c # generates the object file func.o
gcc -c main.c # generates the object file main.o
gcc func.o main.o -o main # generates the executable main
Run Code Online (Sandbox Code Playgroud)

每个目标文件都有外部符号(您可以将其视为公共成员).默认情况下,函数是外部函数,而(全局)变量默认是内部函数.您可以通过定义来更改此行为

static int func(int i) { # static linkage
    return ++i ;
}
Run Code Online (Sandbox Code Playgroud)

要么

/* global variable accessible from other modules (object files) */
extern int global_variable = 10; 
Run Code Online (Sandbox Code Playgroud)

当遇到对主模块中未定义的函数的调用时,链接器将搜索作为定义被调用函数的模块的输入提供的所有目标文件(和库).默认情况下,您可能有一些链接到您的程序的库,这是您可以使用的方式printf,它已经编译到库中.

如果您真的感兴趣,请尝试一些汇编编程.这些名称相当于汇编代码中的标签.


Som*_*ude 14

它是处理所有这些的链接器.编译器只在对象文件中发出一个特殊序列,说明"我有这个外部符号func,请解析它".然后链接器会看到它,并在所有其他目标文件和库中搜索该符号.


Hen*_*rik 5

在同一编译单元中没有定义的符号声明告诉编译器使用该符号地址的占位符编译到目标文件中。

链接器将看到需要符号定义,并将在库和其他目标文件中查找符号的外部定义。

如果链接器找到定义,则原始目标文件中的占位符将替换为最终可执行文件中找到的地址。