如何在C99多文件项目中声明内联函数?

时间:2022-01-24 04:52:54

I want to define an inline function in a project, compiled with c99. How can I do it? When I declare the function in a header file and give the detail in a .c file, the definition isn't recognized by other files. When I put the explicit function in a header file, I have a problem because all .o files who use it have a copy of the definition, so the linker gives me a "multiple definition" error.

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

What I am trying to do is something like:

我想要做的是:

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


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

lib2.c
#include "header.h"

with a utility which uses both lib1.o and lib2.o

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

3 个解决方案

#1


24  

Unfortunately not all compilers are completely complying to C99 in that point even if they claim that they'd be.

不幸的是,并非所有编译器都完全遵守C99,即使他们声称他们是。

An conforming way to do this is

一种符合要求的方法是

// header file. an inline declaration 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);

Newer versions of gcc, e.g, will work fine with that.

较新版本的gcc,例如,可以正常使用。

You may get away with it for other compilers (pretenders) by defining something like

你可以通过定义类似的东西来为其他编译器(伪装者)侥幸逃脱

#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);

Edit:

编辑:

compilers with C99 support (usually option -std=c99) that I know of

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

  • gcc (versions >= 4.3 IIRC) implements the correct inline model
  • gcc(版本> = 4.3 IIRC)实现了正确的内联模型
  • pcc is also correct
  • pcc也是对的
  • ggc < 4.3 needs a special option to implement the correct model, otherwise they use their own model that results in multiple defined symbols if you are not careful
  • ggc <4.3需要一个特殊选项来实现正确的模型,否则他们会使用自己的模型,如果你不小心,会产生多个定义的符号
  • icc just emits symbols in every unit if you don't take special care. But these symbols are "weak" symbols, so they don't generate a conflict. They just blow up your code.
  • 如果您不特别小心,icc只会在每个单元中发出符号。但这些符号是“弱”符号,因此它们不会产生冲突。他们只是炸毁你的代码。
  • opencc, AFAIR, follows the old gcc specific model
  • opencc,AFAIR,遵循旧的gcc特定模型
  • clang doesn't emit symbols for inline functions at all, unless you have an extern declaration and you use the function pointer in one compilation unit.
  • clang根本不为内联函数发出符号,除非你有一个extern声明并且你在一个编译单元中使用函数指针。
  • tcc just ignores the inline keyword
  • tcc只是忽略了内联关键字

#2


4  

If used by itself, in C99 inline requires that the function be defined in the same translation unit as it's being used (so, if you use it in lib1.c, it must be defined in lib1.c).

如果单独使用,则在C99内联中要求函数在与使用它相同的转换单元中定义(因此,如果在lib1.c中使用它,则必须在lib1.c中定义)。

You can also declare a method as static inline (and put the definition in a header file shared between two source files). This avoids the multiple-definition issue, and lets the compiler inline the file across all the translation units where it's used (which it may or may not be able to do if you just declare the function in one translation unit).

您还可以将方法声明为静态内联(并将定义放在两个源文件之间共享的头文件中)。这避免了多重定义问题,并允许编译器在所有使用它的翻译单元中内联文件(如果您只是在一个翻译单元中声明该功能,它可能会或可能不会这样做)。

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

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

#3


-1  

I think you don't need to use the inline word when you are defining and declaring the function inside the Header file, the compiler usually takes it as inline by default unless it's too long, in which case it will be smart enough to treat it as a normal function.

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

I think the multiple definition may be caused by the lack of a Include Guard in the Header file.

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

You should use something like this in the header:

你应该在标题中使用这样的东西:

#ifndef HEADERNAME_H
#define HEADERNAME_H

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

#endif

#1


24  

Unfortunately not all compilers are completely complying to C99 in that point even if they claim that they'd be.

不幸的是,并非所有编译器都完全遵守C99,即使他们声称他们是。

An conforming way to do this is

一种符合要求的方法是

// header file. an inline declaration 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);

Newer versions of gcc, e.g, will work fine with that.

较新版本的gcc,例如,可以正常使用。

You may get away with it for other compilers (pretenders) by defining something like

你可以通过定义类似的东西来为其他编译器(伪装者)侥幸逃脱

#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);

Edit:

编辑:

compilers with C99 support (usually option -std=c99) that I know of

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

  • gcc (versions >= 4.3 IIRC) implements the correct inline model
  • gcc(版本> = 4.3 IIRC)实现了正确的内联模型
  • pcc is also correct
  • pcc也是对的
  • ggc < 4.3 needs a special option to implement the correct model, otherwise they use their own model that results in multiple defined symbols if you are not careful
  • ggc <4.3需要一个特殊选项来实现正确的模型,否则他们会使用自己的模型,如果你不小心,会产生多个定义的符号
  • icc just emits symbols in every unit if you don't take special care. But these symbols are "weak" symbols, so they don't generate a conflict. They just blow up your code.
  • 如果您不特别小心,icc只会在每个单元中发出符号。但这些符号是“弱”符号,因此它们不会产生冲突。他们只是炸毁你的代码。
  • opencc, AFAIR, follows the old gcc specific model
  • opencc,AFAIR,遵循旧的gcc特定模型
  • clang doesn't emit symbols for inline functions at all, unless you have an extern declaration and you use the function pointer in one compilation unit.
  • clang根本不为内联函数发出符号,除非你有一个extern声明并且你在一个编译单元中使用函数指针。
  • tcc just ignores the inline keyword
  • tcc只是忽略了内联关键字

#2


4  

If used by itself, in C99 inline requires that the function be defined in the same translation unit as it's being used (so, if you use it in lib1.c, it must be defined in lib1.c).

如果单独使用,则在C99内联中要求函数在与使用它相同的转换单元中定义(因此,如果在lib1.c中使用它,则必须在lib1.c中定义)。

You can also declare a method as static inline (and put the definition in a header file shared between two source files). This avoids the multiple-definition issue, and lets the compiler inline the file across all the translation units where it's used (which it may or may not be able to do if you just declare the function in one translation unit).

您还可以将方法声明为静态内联(并将定义放在两个源文件之间共享的头文件中)。这避免了多重定义问题,并允许编译器在所有使用它的翻译单元中内联文件(如果您只是在一个翻译单元中声明该功能,它可能会或可能不会这样做)。

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

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

#3


-1  

I think you don't need to use the inline word when you are defining and declaring the function inside the Header file, the compiler usually takes it as inline by default unless it's too long, in which case it will be smart enough to treat it as a normal function.

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

I think the multiple definition may be caused by the lack of a Include Guard in the Header file.

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

You should use something like this in the header:

你应该在标题中使用这样的东西:

#ifndef HEADERNAME_H
#define HEADERNAME_H

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

#endif