即使不包含在 C 中,函数也是可见的

Function visible even if not included in C

我在 main.c 文件中定义了函数 A。我已经创建了三个库,它们使用 A 函数而不导入任何东西。该代码有效,但我只有一个警告:implicit declaration of function 'A' [-Wimplicit-function-declaration].

函数 A 如何在单独文件中定义的函数 B 中工作而不导入它? 当函数 A 被函数 B 以外的其他函数调用时,我怎么可能只有一个警告?

全局非静态符号(变量函数)默认有外部linkage meaning they can be accessed from other translation units.

C 中,我们不“导入”函数。我们将各个翻译单元编译为目标文件,然后 link 将它们全部组合在一起形成二进制文件/可执行文件。

在 linking 阶段,linker 检查目标文件中所需的符号和引用,并将它们 links 在一起以生成单个可执行文件(从而进行函数调用可能在运行时)。

在您的情况下,编译器在调用时不会“看到”函数声明(因此,它对函数签名一无所知,这可能是一个潜在的陷阱,这就是为什么你有“警告”),但在 linking 阶段,linker 能够找到对函数的引用(假设两个翻译单元都是link一起形成二进制文件)并创建二进制文件。

FWIW,根据最新的 C 标准,隐式函数声明是非标准的。您必须 前向声明该函数(提供原型),然后才能实际使用该函数。引用 C11,前言,

Major changes in the second edition included:

[....]

— remove implicit function declaration

正在编译:

  • 编译的时候每个文件都是单独编译的,最后一个.o 文件是从 .c 文件生成的。

  • 对于在文件编译器中调用的每个函数,编译器期望函数定义或至少函数声明。

  • 如果缺少定义或声明,编译器会发出警告,例如函数的隐式声明 'A'
    [-Wimplicit-function-declaration].

  • 在您的情况下,函数定义在另一个文件中,您必须至少在包含文件中包含函数声明。

链接:

  • 链接是指从
    创建单个可执行文件 多个目标文件。在这一步中,常见的是linker
    会抱怨未定义的函数。

  • 由于main.c中的函数A是全局定义的,它将被库使用。