gpt4 book ai didi

c - 外部链接内联函数定义是否需要 `extern`?

转载 作者:行者123 更新时间:2023-12-03 08:42:12 25 4
gpt4 key购买 nike

GCC 可以将以下 .c 文件编译并链接为可执行文件:

ma​​in.c

#include <stdio.h>
#include "addsub.h"

int main(void)
{
printf("%d %d\n", add(1, 2), sub(1, 2));
return 0;
}

addsub.c

#include "addsub.h"

inline int add(int a, int b)
{
return a + b;
}

int sub(int a, int b)
{
return add(a, -b);
}

addsub.h

#ifndef ADDSUB_H__
#define ADDSUB_H__

int add(int, int);
int sub(int, int);

#endif

根据C116.7.4 函数说明符,第 7 段:

[...] 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. [...]

上面的任何函数声明中均未使用 extern 关键字,因此 GCC 在“addsub.c”中提供 add 函数的外部定义是否正确“?

6.2.2标识符的链接中,第5段说:

If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier extern. [...]

但是,当省略 extern 关键字时,这似乎并不能证明向内联 add 函数添加外部链接是合理的。

最佳答案

是的,GCC 运行正确。但它并没有按照您的指示自行添加外部定义。

关键是理解什么是“外部定义”。

6.9 External definitions

4 As discussed in 5.1.1.1, the unit of program text after preprocessing is a translation unit, which consists of a sequence of external declarations. These are described as ''external'' because they appear outside any function (and hence have file scope). As discussed in 6.7, a declaration that also causes storage to be reserved for an object or a function named by the identifier is a definition.

5 An external definition is an external declaration that is also a definition of a function (other than an inline definition) or an object. If an identifier declared with external linkage is used in an expression (other than as part of the operand of a sizeof or _Alignof operator whose result is an integer constant), somewhere in the entire program there shall be exactly one external definition for the identifier; otherwise, there shall be no more than one.

或多或少,外部定义是在文件范围内定义的任何内容。理解此处行为的关键是仅使用 inline 说明符声明的函数不提供外部定义。这大致意味着翻译单元不拥有此函数的符号。因此,如果程序仅包含函数的内联定义,则链接可能会失败。

为什么在你的情况下它没有失败?这是因为 addsub.c 包含 addsub.h。该翻译单元的样子是

int add(int, int);
int sub(int, int);

inline int add(int a, int b)
{
return a + b;
}

int sub(int a, int b)
{
return add(a, -b);
}

顶部的 add 外部声明使得“内联定义”也成为外部定义。根据您引用的段落

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.

显然,并非函数的每个声明都只包含 inline 说明符(本例中的第一个声明),因此 addsub.c 中的定义实际上是一个外部定义。

关于c - 外部链接内联函数定义是否需要 `extern`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62392929/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com