27

我想在项目中定义一个内联函数,用c99编译。我该怎么做?当我在头文件中声明函数并在 .c 文件中提供详细信息时,其他文件无法识别该定义。当我将显式函数放在头文件中时,我遇到了问题,因为使用它的所有 .o 文件都有定义的副本,因此链接器给了我一个“多重定义”错误。

我想做的是这样的:

header.h
inline void func()
{
    do things...
}


lib1.c
#include "header.h"
...

lib2.c
#include "header.h"

使用同时使用 lib1.o 和 lib2.o 的实用程序

4

3 回答 3

29

不幸的是,并非所有编译器都完全符合 C99,即使他们声称会这样做。

一种符合要求的方法是

// header file. an inline definition alone is
// not supposed to generate an external symbol
inline void toto(void) {
  // do something
}

// in one .c file, force the creation of an
// external symbol
extern inline void toto(void);

例如,较新版本的 gcc 可以正常工作。

您可以通过定义类似的东西来为其他编译器(伪装者)摆脱它

#ifdef PRETENDER
# define inlDec static
# define inlIns static
#else
# define inlDec 
# define inlIns extern
#endif
// header file. an inline declaration alone is
// not supposed to generate an external symbol
inlDec inline void toto(void) {
  // do something
}

// in one .c file, force the creation of an
// external symbol
inlIns inline void toto(void);

编辑:

-std=c99我知道的支持 C99 的编译器(通常是 option )

  • gcc (versions >= 4.3 IIRC) 实现了正确的inline模型
  • pcc也是正确的
  • ggc < 4.3 需要一个特殊的选项来实现正确的模型,否则他们使用自己的模型,如果你不小心会导致多个定义的符号
  • 如果您不特别注意,icc 只会在每个单元中发出符号。但是这些符号是“弱”符号,所以它们不会产生冲突。他们只是炸毁了你的代码。
  • opencc,AFAIR,遵循旧的 gcc 特定模型
  • clang 根本不会为inline函数发出符号,除非您有extern声明并且在一个编译单元中使用函数指针。
  • tcc 只是忽略inline关键字
于 2011-03-08T07:22:12.397 回答
5

如果单独使用,在 C99 中inline要求该函数在与它所使用的相同的翻译单元中定义(因此,如果您在 lib1.c 中使用它,它必须在 lib1.c 中定义)。

您还可以将方法声明为static inline(并将定义放在两个源文件之间共享的头文件中)。这避免了多定义问题,并让编译器在使用它的所有翻译单元中内联文件(如果您只是在一个翻译单元中声明函数,它可能会或可能无法做到)。

见: http ://www.greenend.org.uk/rjk/2003/03/inline.html

于 2011-03-08T07:06:04.100 回答
-1

我认为在 Header 文件中定义和声明函数时不需要使用 inline 字,编译器通常默认将其视为 inline 除非它太长,在这种情况下它会足够聪明地对待它作为正常功能。

我认为多重定义可能是由于 Header 文件中缺少 Include Guard 造成的。

您应该在标题中使用类似这样的内容:

#ifndef HEADERNAME_H
#define HEADERNAME_H

void func()
{
    // do things...
}

#endif
于 2011-03-08T07:04:13.497 回答