我正在尝试了解外部内联和内联函数。
What's the difference between static inline, extern inline and a normal inline function?
从以上链接引用行: "仅使用内联的函数定义定义了具有外部链接的内联函数。但是,这种定义称为内联定义,它不能作为该函数的外部定义。这意味着即使此函数具有外部链接,它也将被视为未定义其他翻译单元,除非您在某处为其提供单独的外部定义。
带有extern inline的函数定义定义了具有外部链接的内联函数,同时该定义用作此函数的外部定义。可以从其他翻译单元调用此类功能。"
但我无法正确理解这一点。
我有一个示例代码,解释了我的理解:
在temp1.c中
#include <stdint.h>
extern int32_t fun1(void);
int32_t main(void)
{
int32_t result = fun1();
return result;
}
在temp2.c中
#include <stdint.h>
int32_t fun1(void);
inline int32_t fun1(void)
{
return 0;
}
由于fun1是temp2.c中的内联定义,因此将从temp1.c中看作未定义。因此temp1.c中的外部声明使temp1.c从temp2.c访问fun1。我很困惑,因为在它引用的引用中&#34;单独的外部定义&#34;而不是外部声明。
temp1.c文件名
#include <stdint.h>
int32_t fun1(void);
int32_t main(void)
{
int32_t result = fun1();
return result;
}
temp2.c
#include <stdint.h>
extern inline int32_t fun1(void)
{
return 0;
}
由于fun1是extern内联函数,因此可以从temp1.c中调用它。 我观察到的唯一区别是,无需在定义它的情况下明确声明extern内联函数。
这是唯一的区别吗?否则内联和外部内联函数的其他主要区别和范围是什么?
如果上述观察结果有误,请更正
答案 0 :(得分:3)
关于第一个&#34;内联函数&#34;例如,你说(突出显示添加到函数名称),
由于
访问fun1
是temp2.c中的内联定义,因此它将被视为 从temp1.c中未定义。所以在temp1.c中做了外部声明 temp1.c从temp2.c。fun1
你的解释不正确,或者至少是错误的。 在此示例中,temp2.c不提供函数。 temp2.c中的函数fun1()
的外部定义。 temp1.c中的声明表示外部定义某处,但temp2.c不是那个地方。需要有一些其他翻译单元提供的外部定义fun1
是内联函数,因为它是使用inline
关键字声明的(这意味着&#39;所有这意味着成为&# 34;内联函数&#34;),但该文件中fun1
的定义不是内联定义,因为temp2.c包含其另一个声明不包含inline
关键字的标识符。由于fun1
是使用(隐式)外部链接声明的,因此fun1
的外部定义。任何人都可以打电话。要获得函数的内联定义, TU中其标识符的每个声明必须包含inline
关键字,并且必须省略extern
关键字。
标准C确实要求在temp1.c中声明该函数,如果要从该TU调用该函数,但是您在该文件中放置的任何内容都不能使其中的代码访问{{1}的内联定义来自不同的TU。只有外部定义可以通过TU访问 - 这就是外部定义的含义。
注意 :这部分答案的原始(现在已经删除)文本假设temp2.c确实提供了函数的内联定义fun1
,因为我忽略了声明中的缺陷(?)。
我在报价中感到困惑 是说&#34;分开外部定义&#34;而不是外在的 声明。
函数定义包含该函数的声明,但并非每个函数声明都是定义的一部分。我们必须小心这里的措辞。没有任何意义上的&#34;外部函数声明&#34;在C中,没有声明的范围比其翻译单元宽。
但是,人们可以并且经常会使用外部链接来(函数)声明函数。这是默认值,适用于不包含关键字fun1
的所有函数声明。可以通过使用static
关键字使该默认值明确,并且这对于内联函数的声明具有额外的意义。
另一方面,外部函数定义是可以通过其他翻译单元的名称访问的函数。内联定义显式不是外部定义。因此,您的第一个示例声明存在具有外部链接的函数extern
,但如果该标识符的所有声明都带有fun1
关键字而不是{{1>,则不那么它就不会提供该函数的相应外部定义。如果调用该函数 ,即使是从提供内联定义的源文件调用,那么缺少外部定义 将是一个错误。
关于第二个&#34; extern内联函数&#34;例如,你说(突出显示添加到函数名称),
由于
调用它inline
是外部内联函数,因此可以从temp1.c。
让我们在这里分开属性。
extern
(仍然)被声明为具有外部链接的函数。fun1
说明符的存在是其定义的一部分,使其成为内联函数。fun1
说明符的存在使得该TU中的定义成为外部定义。事实上,temp2.c中的定义是一个外部的定义,使得它可以从temp1.c中调用。
我观察到的唯一区别是,无需明确 声明外部内联函数的声明。
在第一个例子中也不需要 inline
的前向声明。如果temp2.c在该函数的定义之前包含对extern
的调用,则需要在两个情况下进行前向声明。这里没有区别。
更新
你或多或少是对的。您的两种选择是使用外部链接声明内联函数并为其提供外部定义的不同方法。相反,你应该比较的东西,以及错误地解决这个答案的原始文本的东西是这样的:
fun1()
或等效地:
fun1
在这些情况下,#include <stdint.h>
inline int32_t fun1(void);
inline int32_t fun1(void)
{
return 0;
}
提供的定义是内联定义,只能从temp2.c的翻译单元访问。当然,除非该TU中的代码实际调用该函数,否则这没有用。
这是唯一的区别吗?否则,其他主要区别是什么 内联和外部内联函数的范围?
你试图设置&#34; inline&#34;你自己也是一种伤害。和&#34; extern inline&#34;作为功能类。有内联函数和非内联函数。有内部链接的函数标识符和具有外部链接的函数。有内联函数定义,内部函数和外部函数,并且TU中函数声明的出现不一定需要在同一个TU中定义。这些属性的这些组合(并且只有这些)是可能的:
在给定TU中使用外部链接声明的函数标识符是指外部函数定义,它可能出现在不同的TU中。
在给定TU中使用内部链接声明的函数标识符引用同一TU中的内部或内联函数定义。
内联函数声明可以具有外部或内部链接,在任何一种情况下,该函数的内联定义必须出现在同一个TU中。如果函数标识符具有外部链接(在该TU中)和内联函数定义,则由实现自行决定是否以及在该TU内使用其他地方的内联定义或(必需的)外部定义。
更新
经过反思,您将函数本身表征为&#34;内联函数&#34;和&#34; extern内联函数&#34;似乎反映了一个功能的内联字符全局与函数的标识符(例如#include <stdint.h>
inline int32_t fun1(void)
{
return 0;
}
)相关联的想法,至少对于具有外部链接的标识符。事实并非如此,因为我希望我的话语相当冗长。
函数标识符的内联字符是per-TU属性,函数定义的内联字符是单独的每个定义属性。如果在任何TU中您将给定函数声明为内联函数,则必须在该TU中提供该函数的定义。来自不同TU的函数的外部定义不满足该要求,即使该函数被声明为定义出现的TU中的内联函数。