内联函数多重定义

Inline function multiple definition

我有以下三个文件:

inline_header.h

#ifndef INLINE_HEADER_H
#define INLINE_HEADER_H

inline int func1() {
    return 1;
}

#endif

source1.c

#include "inline_header.h"

source2.c

#include "inline_header.h"

int main() {
    func1();
}

当我只编译 source2.cgcc source2.c 时,它会编译。但是,当我尝试使用 gcc source1.c source2.c 进行编译时,出现如下多重定义错误:

/tmp/cchsOaHF.o: In function `func1':
source2.c:(.text+0x0): multiple definition of `func1'
/tmp/ccEyUW0T.o:source1.c:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status

我正在 Ubuntu 14.04 上使用 gcc 4.8.4 进行编译。

我尝试查找此问题并发现了一个类似的问题 multiple definition of inline function。但是在他的例子中,错误是由他的内联函数的重新定义引起的。就我而言,我没有重新定义它(或者至少没有明确...)。

如果您希望将此类函数放在 header 中,它也必须是 static:

static inline int func1() {
    return 1;
}

这将导致符号对于每个编译单元(文件)都是本地的,避免任何链接器错误。

此外,来自 gcc manual:

When an inline function is not static, then the compiler must assume that there may be calls from other source files; since a global symbol can be defined only once in any program, the function must not be defined in the other source files, so the calls therein cannot be integrated. Therefore, a non-static inline function is always compiled on its own in the usual fashion.

当你将source1.c编译成source1.o时,它包含了func1的定义。同样,当你把source2.c编译成source2.o时,它也包含了func1的定义。所以当你 link source1.o 和 source2.o 时,你会得到一个多重定义错误。

include guards 不阻止的原因是因为 source1.c 和 source2.c 都是单独编译的。包含守卫仅在单个编译单元内提供帮助。

如果这不是内联函数,您将在头文件中声明:

int func1();

然后将定义放在一个源文件中。

但是,您将函数定义为 inline。因此您还需要将其声明为 static 以便每个编译单元都获得自己的函数副本。

编辑:

出现多重定义错误是因为您默认在 C89 模式下编译,而 inline 不是该版本标准的一部分。因此,gcc 似乎基本上忽略了该关键字。

如果您在 C99 或 C11 模式下使用此代码使用 -std=c99=std=c11 进行编译,您实际上会收到“未定义引用”错误。 C 标准的第 6.7.4p7 节规定如下:

Any function with internal linkage can be an inline function. For a function with external linkage, the following restrictions apply: If a function is declared with an inline function specifier, then it shall also be defined in the same translation unit. If all of the file scope declarations for a function in a translation unit include the inline function specifier without extern, then the definition in that translation unit is an inline definition. An inline definition does not provide an external definition for the function,and does not forbid an external definition in another translation unit. An inline definition provides an alternative to an external definition, which a translator may use to implement any call to the function in the same translation unit. It is unspecified whether a call to the function uses the inline definition or the external definition

这意味着只有 inline 的函数实际上并没有提供可调用函数的定义。在您的情况下,您想要添加 static 存储 class 说明符以强制在每个文件中进行本地定义。

有趣的是,如果您使用 -O1-std=c99 编译此代码,gcc 将在物理上内联该函数,并且它会编译 运行 干净。