来自 C18 标准:
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.
然后我们读到:
The declaration of an inline function with external linkage can result in either an external definition, or a definition available for use only within the translation unit. A file scope declaration with extern creates an external definition.
我已经编写了一些代码来检查该函数是否实际上是内联的。我已经使用此限制来找出:
An inline definition of a function with external linkage shall not contain a definition of a modifiable object with static or thread storage duration, and shall not contain a reference to an identifier with internal linkage.
这是代码:
static int n = 5;
void inline foo() { n = 66; }
void inline foo(); // remove 'inline' in second version
int main() {
return 0;
}
编译时,我收到一条警告说内联函数正在使用静态对象,这意味着 foo()
实际上,它是一个内联函数,因此它提供了一个内联(而非外部)定义。但是,当我删除 inline
时来自指示行的说明符,我不再收到警告。根据标准,它不是内联定义,所以我猜它提供了外部定义。标准没有说,或者至少我看不到,是提供外部定义的内联函数是否不再是内联函数。根据我的测试,它确实不再是内联函数。
如果我的结论是正确的(我不知道),那么就会出现另一个问题:为什么 extern 内联函数是无用的东西?
最佳答案
在问题中,您尝试在编译器中尝试并推断语言规则。这通常是一个坏主意,因为 (a) 在许多情况下,违反规则的影响很难观察到,并且 (b) 编译器可能会被窃听。相反,标准是语言规则的权威来源,因此应通过引用标准来回答问题。
继续:您的代码包含违反 C11 6.7.4/3 的约束,您在问题中引用了该约束。违反约束的结果是编译器必须发出诊断,它确实做到了。
然后你问一些修改,我假设你的意思是以下代码:
static int n = 5;
void inline foo() { n = 66; }
void foo();
int main() { return 0; }
正如您引用的第一句话(来自 6.7.4/7)所涵盖的那样,foo()
的定义不是内联定义,因为并不是所有 TU 中的文件范围声明都包含 inline
不带 extern
的说明符. (这句话的意思是 deny the antecedent )。由于不是内联定义,所以
n = 66
没有问题并且代码是正确的。What the standard is not saying, or at least I cannot see it, is whether an inline function that provides an external definition stops being an inline function, or not
内联函数定义绝不是外部定义。这在 6.7.4/7“内联定义不提供函数的外部定义”中有明确说明。
也许您的困惑源于将概念“内联函数定义”和“函数定义与
inline
说明符”混为一谈。another question arises: why an extern inline function is a useless thing?
如果您的意思是关键字
extern inline
这是这个问题没有涉及的另一个话题,see here .带有外部链接的内联函数当然不是无用的。
关于c - 外部链接内联函数真的是内联的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63629807/