inline void foo();
int main() {
foo(); return 0;
}
void foo(){
}
将foo
的声明设为inline
而非foo
的定义是否有任何区别?对面怎么样?如何将它们标记为inline
?
答案 0 :(得分:4)
这是C11关于内联的所有内容(注意:inline
是函数说明符,目前唯一的其他函数说明符是_Noreturn
)(强调我的):
6.7.4
2。函数说明符只能用于声明函数的标识符。
3。具有外部链接的函数的内联定义不应包含a的定义 具有静态或线程存储持续时间的可修改对象,且不得包含引用 到具有内部联系的标识符。
5。函数说明符可能出现多次;行为和它一样 只出现过一次。
6。使用内联函数说明符声明的函数是内联函数。制作一个 函数内联函数表明对函数的调用应尽可能快。 138 这些建议有效的程度是实施定义的。 139
7。具有内部链接的任何函数都可以是内联函数。用于外部功能 链接,以下限制适用:如果使用内联声明函数 函数说明符,那么它也应该在同一个翻译单元中定义。 如果全部的话 翻译单元中函数的文件范围声明包括内联函数 没有extern的说明符,那么该翻译单元中的定义是内联的 定义。 内联定义不提供函数的外部定义, 并且不禁止在另一个翻译单元中使用外部定义。内联定义 提供了外部定义的替代方案,翻译人员可以使用该定义来实现 在同一翻译单元中对该功能的任何调用。没有具体说明是否打电话给 函数使用内联定义或外部定义。
10。示例1使用外部链接声明内联函数可能会导致外部链接 定义或仅可在翻译单元内使用的定义。带有的文件范围声明 extern创建一个外部定义。以下示例显示了整个翻译单元。
inline double fahr(double t) { return (9.0 * t) / 5.0 + 32.0; } inline double cels(double t) { return (5.0 * (t - 32.0)) / 9.0; } extern double fahr(double); // creates an external definition double convert(int is_fahr, double temp) { /* A translator may perform inline substitutions */ return is_fahr ? cels(temp) : fahr(temp); }
11。请注意,
fahr
的定义是外部定义,因为fahr
也是使用extern声明的,但是cels
的定义是内联定义。因为cels
具有外部链接并被引用,所以 外部定义必须出现在另一个翻译单元中(见6.9);内联定义和外部定义 定义是不同的,可以用于呼叫。138 例如,使用通常的函数调用机制的替代方法,例如''inline 代换''。内联替换不是文本替换,也不是创建新函数。 因此,例如,函数体内使用的宏的扩展使用了 它在函数体出现时的定义,而不是调用函数的位置;和 标识符指的是正文出现的范围内的声明。同样,该功能有一个 单个地址,不管外部发生的内联定义的数量 定义
139 例如,实现可能永远不会执行内联替换,或者可能只执行内联 替换为内联声明范围内的调用
6.9
5。外部定义是外部声明,也是函数的定义 (内联定义除外)或对象。
J.1未指明的行为
- 对内联函数的调用是使用内联定义还是外部定义 功能(6.7.4)。
J.2未定义的行为
- 使用内联函数说明符声明具有外部链接的函数,但是 也没有在同一翻译单元(6.7.4)中定义。
J.3实现 - 定义行为
J.3.8提示
- 使用内联函数说明符进行建议的程度 有效(6.7.4)。
6.7.4.3
:如果链接器也可以看到内联函数,则它不能有static
个局部变量。
它也不能使用文件范围变量/函数(定义为全局标识符,但使用static
)。 (注意:可以有人
告诉我对这最后一句话的理解是否正确?这感觉不对。)
6.7.4.6
:使函数内联不会强制编译器像一个宏一样行动。它只是提示编译器
你希望功能快。
6.7.4.7
:
static
功能,则可以将其设为inline
。inline
函数声明,
在同一个TU的某个地方,它应该能够找到它的定义。inline
的函数,那么编译器会将该函数看作static
(但不完全正确)。 138
:无论您在不同的TU中定义内联函数多少次,它们都有"相同的"地址。我相信
这也意味着如果你使用函数指针来存储地址,然后通过那个指针调用函数,那么
将调用函数的外部定义。
6.9.5
:正常的函数定义既声明又定义了外部函数。但正如我们在内联定义之前看到的那样
该函数没有定义一个外部可见的定义,即使它可以声明一个外部函数。
1 在您的示例中,如果您在inline
的定义中放置foo
,则gcc会收到错误(在链接阶段)
foo
有未定义的引用。如果将foo
的另一个实现放在同一个文件中,则会出现重新定义错误。
这与我所说的一致:全内联声明/定义不提供外部链接,如果使用该功能
在TU中,它需要在另一个TU中定义。
进一步阅读: