c - 内联函数的多重定义

标签 c inline

我浏览了一些与此主题相关的帖子,但无法完全解决我的疑问。这可能是一个非常幼稚的问题。

我有一个头文件 inline.h 和两个翻译单元 main.cpptran.cpp

具体代码如下

内联.h

#ifndef __HEADER__
#include <stdio.h>
extern inline int func1(void)
{ return 5; }

static inline int func2(void)
{ return 6; }

inline int func3(void)
{ return 7; }
#endif

主.c

#define <stdio.h>
#include <inline.h>
int main(int argc, char *argv[])
{
    printf("%d\n",func1());
    printf("%d\n",func2());
    printf("%d\n",func3());
    return 0;
}

转录.cpp

//(note that the functions are not inline here)
#include <stdio.h>
int func1(void)
{ return 500; }

int func2(void)
{ return 600; }

int func3(void)
{ return 700; }

以上代码在 g++ 中编译,但在 gcc 中不编译(即使您进行了与 gcc 相关的更改,例如将代码更改为 .c,不使用任何 C++ 头文件等)。显示的错误是“内联函数的重复定义 - func3”。

您能否阐明为什么编译器之间存在这种差异?

此外,当您通过创建两个单独的编译单元(main.otran.o)运行程序(g++ 编译)并创建可执行文件时 a.out,得到的输出为:

500
6
700

为什么编译器选择非内联函数的定义。实际上,因为 #include 用于“添加”内联定义,所以我期望 5,6,7 作为输出。我的理解是在编译期间,因为找到内联定义,函数调用将被内联函数定义“替换”。

能否请您详细告诉我编译和链接过程的详细步骤,这将使我们得到 500,6,700 输出。我只能理解输出6。

最佳答案

本回答分为以下几个部分:

  1. 如何重现 duplicate definition of inline function - func3 问题以及原因。
  2. 为什么 func3 的定义与 func1 重复。
  3. 为什么使用 g++ 编译

如何产生内联函数的重复定义-func3问题

问题可以成功复现

  1. tran.cpp 重命名为 tran.c
  2. gcc -o main main.c tran.c 编译

@K71993 实际上是使用旧的 gnu89 内联语义进行编译,这与 C99 不同。tran.cpp 重命名为 tran.c< 的原因 是告诉 gcc 驱动程序将其视为 C 源而不是 C++ 源。


为什么 func3 的定义与 func1 重复。

GNU 89 内联语义

以下文字引自GCC Document: An Inline Function is As Fast As a Macro解释了为什么 func3 是重复定义而不是 func1,因为 func3(而不是 func1)是一个外部可见的符号(在 GNU89 内联语义中)

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.

If you specify both inline and extern in the function definition, then the definition is used only for inlining. In no case is the function compiled on its own, not even if you refer to its address explicitly. Such an address becomes an external reference, as if you had only declared the function, and had not defined it.

C99 内联语义

如果使用 C99 标准编译,即 gcc -o main main.c tran.c -std=c99,链接器会提示 func1 的定义是一个重复是因为 C99 中的 extern inline 是其他帖子和评论中提到的外部定义。

另请引用this关于 GNU89 inlineC99 inline 之间的语义差异的出色回答。

为什么使用g++编译。

当使用g++编译时,源程序被认为是C++源代码。由于func1func2func3在多个翻译单元中定义且定义不同,One Defintion Rule of C++被侵犯。由于定义跨越多个翻译单元时编译器不需要生成诊断消息,因此行为未定义。

关于c - 内联函数的多重定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2722276/

相关文章:

c++ - inline 关键字对类成员模板函数的影响?

css - 如何在不指定宽度的情况下将 html 表格保持在同一行?

c - 排列四个4位二进制数的程序

c - 使用 getchar() 而不是 scanf() 的问题

c - 将 fgets 与 realloc() 结合使用

c - 为数组成员设置计时器

c - 为什么结构大小随结构中的枚举位域而变化(标准 C)

虚拟继承函数的 C++ 内联

c++ - 如何使用 typedef 或内联在 C++ 中调用此 x86 ASM CALL

python - Mailgun 内联图像 utf-8 png