静态内联函数、外部内联函数和普通内联函数有什么区别?

43

static inlineextern inline和普通的inline函数有什么区别?

我看到过一些含糊不清的解释。据我所了解,static inline并不仅仅是指一个只能在某个文件中被引用的inline函数,就像static关键字通常表示的那样。我猜extern inline也是同样的情况,它与extern变量的解释不同。如果有任何答案,将不胜感激!


可能重复:https://dev59.com/vWsz5IYBdhLWcg3wn5ba - user1551592
1
所有这些都是内联函数。static inline 是指静态函数,extern inline 是指外部声明的函数,普通 inline 则是普通的。 - MAKZ
可能重复:https://dev59.com/RXVC5IYBdhLWcg3wrDNd - Hsi-Hung Shih
1
请阅读 https://dev59.com/vWsz5IYBdhLWcg3wn5ba#7767858,以下是与编程有关的内容。 - MAKZ
可能是 extern inline 的重复问题。 - o11c
1个回答

39
使用 static inline 定义函数会定义一个带有内部链接的内联函数。这种函数能够按照所期望的方式工作,具有这两个修饰符的通常特性: static 赋予其内部链接性,inline 则使其成为内联函数。因此,该函数是“局部”的于某个翻译单元并在其中进行内联。
使用只有 inline 的函数定义会定义一个带有外部链接的内联函数。但是,这样的定义被称为 内联定义,它不起到这个函数的 外部定义 的作用。这意味着即使这个函数有外部链接,除非你在其他翻译单元中提供一个单独的 外部定义 ,否则它将被视为是 未定义的
使用 extern inline 的函数定义会定义一个具有外部链接的内联函数,同时该定义也作为该函数的 外部定义。这种函数可以从其他翻译单元中调用。
最后两段意味着您可以选择为具有外部链接的内联函数提供单个 extern inline 定义,或为其提供两个单独的定义:一个是 inline,另一个是 extern。在后一种情况下,当您调用函数时,编译器可以选择两个定义中的任意一个。

2
澄清您最后一段的意思:为了提供两个不同的定义,没有必要(事实上也不建议)提供两个函数体。相反,extern inline void f(); 看起来像是一个声明,但实际上它将之前的 inline void f() { ..... } 转换为该单元的外部定义,而不是内联定义。(参考 C11 6.7.4/7)。 - M.M
9
阅读这个答案时,我在理解"外部定义"和"内部定义"的确切含义上遇到了困难。哪里可以找到更多相关信息? - learnlearnlearn
在C11编译器中,inline int il_fun0(void) { return 0; } extern int il_fun0(void) { return 0; }同时提供两个不同的定义会导致"error: redefinition of 'il_fun0'"错误(无论是否使用extern)。因此,请提供两个单独的定义。 - chux - Reinstate Monica
@learnlearnlearn 内联定义用于函数内联。外部定义用于通常的函数调用。inline关键字只是编译器的提示,因此无法保证您的函数调用是否会被编译为内联或普通调用。因此,我们应该为同一个内联函数准备两个定义。每个调用内联函数的翻译单元必须有自己的内联定义来处理内联。此外,只有一个翻译单元必须具有外部定义来处理正常调用。 - rosshjb
例如,当您关闭编译器的优化选项时,内联函数调用将被编译为普通函数调用。在这种情况下,所有普通调用都引用唯一的外部定义。而当您打开优化选项时,内联函数调用将被编译为内联。在这种情况下,通过每个翻译单元自己的内联定义来实现内联。因此,我们在头文件中放置 inline void func(void) {} 以进行内联,并在源文件(单独的翻译单元)中放置 extern inline void func(void); 以进行普通调用。 - rosshjb

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接