内联函数多重定义

kev*_*lbs 5 c gcc inline

我有以下三个文件:

inline_header.h

#ifndef INLINE_HEADER_H
#define INLINE_HEADER_H

inline int func1() {
    return 1;
}

#endif
Run Code Online (Sandbox Code Playgroud)

source1.c

#include "inline_header.h"
Run Code Online (Sandbox Code Playgroud)

source2.c

#include "inline_header.h"

int main() {
    func1();
}
Run Code Online (Sandbox Code Playgroud)

当我编译只是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
Run Code Online (Sandbox Code Playgroud)

我正在使用Uccntu 14.04上的gcc 4.8.4进行编译.

我试过看了这个,发现了一个类似的问题,内联函数的多个定义.但是在他的情况下,错误是由他的内联函数的重新定义引起的.就我而言,我没有重新定义它(或者至少没有明确地......).

dbu*_*ush 15

将source1.c编译为source1.o时,它包含的定义func1.类似地,当您将source2.c编译为source2.o时,它还包含一个定义func1.因此,当您链接source1.o和source2.o时,会出现多重定义错误.

包含保护不会阻止这种情况的原因是因为source1.c和source2.c都是单独编译的.在单个编译单元中仅包含防护装置.

如果这不是内联函数,则在头文件中放置一个声明:

int func1();
Run Code Online (Sandbox Code Playgroud)

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

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

  • @DonSlowik 使用 `inline` 并不能保证该函数是物理内联的。这只是给编译者的一个提示。由于这是 C,您实际上需要查看 https://en.cppreference.com/w/c/language/inline 以及 C 标准的第 6.7.4 节。 (2认同)
  • @DonSlowik 实际上,应该是这样,但比这更复杂。OP以C89模式编译。我会更新以反映。 (2认同)

Fat*_*ror 8

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

static inline int func1() {
    return 1;
}
Run Code Online (Sandbox Code Playgroud)

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

另外,从gcc 手册:

当内联函数不是静态的时,编译器必须假定可能存在来自其他源文件的调用; 由于全局符号只能在任何程序中定义一次,因此不能在其他源文件中定义该函数,因此无法集成其中的调用.因此,非静态内联函数总是以通常的方式自行编译.