C中区分extern inline和inline

Differentiate extern inline and inline in C

我正在尝试了解外部内联和内联函数。

What's the difference between static inline, extern inline and a normal inline function?

引用上面的几行link: “仅内联的函数定义定义了具有外部 linkage 的内联函数。但是,这种定义称为内联定义,它不能用作该函数的外部定义。这意味着即使此函数具有external linkage,它将被其他翻译单元视为未定义,除非您在某处为其提供单独的外部定义。

A function definition with extern inline 定义了一个inline function with external linkage 同时这个定义作为这个函数的外部定义。可以从其他翻译单元调用此类功能。"

但我无法正确理解这一点。

我有一个示例代码可以解释我的理解:

  1. 内联函数:

在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。我很困惑,因为它在引号中说 "separate external definition" 而不是外部声明。

  1. 外部内联函数

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中调用。 我观察到的唯一区别是,不需要在定义外部内联函数的地方显式声明它。

这是唯一的区别吗?否则内联和外部内联函数的其他主要区别和范围是什么?

以上观察如有错误请指正

关于第一个 "inline function" 示例,您说(突出显示添加到函数名称),

Since fun1 is a inline definition in temp2.c, it will be seen as undefined from temp1.c. So external declaration in temp1.c made temp1.c to access fun1 from temp2.c.

您的解释不正确,或者至少是措辞错误在此示例中,您的 temp2.c 未提供函数 fun1() 的外部定义。 temp1.c中的声明说在某处有一个外部定义,但temp2.c不是那个地方。需要有一些其他翻译单元提供的外部定义temp2.c 中的函数 fun1 内联函数,因为它是用 inline 关键字声明的(这就是全部意思"inline function"),但是 fun1 在该文件中的定义 不是 内联 定义,因为 temp2.c 包含另一个不包含 inline 关键字的标识符声明。由于 fun1 是使用(隐式)外部链接声明的,因此是 fun1 外部 定义。任何人都可以调用它。要获得函数的内联定义, TU 中其标识符的每个 声明都必须包含 inline 关键字并且必须省略 extern 关键字。

如果要从那个 TU 调用函数,标准 C 确实需要在 temp1.c 中声明该函数,但是您在该文件中放置的任何内容都不能启用其中的代码来访问内联来自不同 TU 的 fun1 的定义。跨 TU 只能访问外部定义——这就是外部定义的含义。

注意:该答案这部分的原始(现已删除)文本假定 temp2.c 确实提供了内联定义函数 fun1,因为我忽略了声明中的缺陷(?)。

I am confused as in the quotes it is saying "separate external definition" instead of external declaration.

函数定义包含该函数的声明,但并非每个函数声明都是定义的一部分。我们必须小心这里的措辞。在 C 中,"external function declaration" 没有任何意义,因为没有声明的范围比其翻译单元更宽。

但是人们可以并且经常使用 外部链接 的(本地)函数声明。这是默认值,适用于所有不包含关键字 static 的函数声明。该默认值可以通过使用 extern 关键字来明确显示,这恰好对内联函数的声明具有额外的意义。

另一方面,外部函数定义是可以从另一个翻译单元通过名称访问的函数。内联定义明确不是外部定义。因此,您的第一个示例声明有一个带有外部链接的函数 fun1,但是如果该标识符的所有声明都带有 inline 关键字而不是 则不会 extern 那么它不会提供该函数的相应外部定义。如果该函数 is 被调用,即使是从提供内联定义的源文件中调用,那么缺少外部定义 is 将是一个错误.


关于第二个 "extern inline function" 示例,您说(突出显示添加到函数名称),

Since fun1 is extern inline function, it can be called from temp1.c.

让我们在这里分离出属性。

  • fun1 被(仍然)声明为具有外部链接的函数。
  • 作为其定义一部分的声明中存在 inline 说明符使其成为内联函数。
  • 在与定义相同的翻译单元中,该函数声明中显式 extern 说明符的存在使得该 TU 中的定义成为外部定义。

事实上 temp2.c 中的定义是一个外部定义,这使得它可以从 temp1.c 调用。

The only difference what I observed is, no need of explicit declaration of the extern inline function where it is defined.

在第一个示例中也不需要前向声明 fun1()。如果 temp2.c 在该函数定义之前包含对 fun1 的调用,则在 两种 情况下都需要前向声明。这里没有区别。


更新:

你或多或少是对的。您的两种选择是声明具有外部链接的内联函数并为其提供外部定义的不同方式。相反,你应该比较的东西,以及这个答案的原文被错误地提到的东西,将是这样的:

#include <stdint.h>

inline int32_t fun1(void);

inline int32_t fun1(void)
{
   return 0;
}

或者,等效地,这个:

#include <stdint.h>

inline int32_t fun1(void)
{
   return 0;
}

在这些情况下,提供的 fun1 定义是内联定义,只能从 temp2.c 的翻译单元访问。当然,除非该TU中有实际调用该函数的代码,否则这没有用。


Is it the only difference ? else what are the other major difference and the scope of inline and extern inline functions ?

您试图将 "inline" 和 "extern inline" 设置为 类 函数是在伤害自己。有内联函数和非内联函数。函数 identifiers 具有内部链接和外部链接。有内联函数定义、内部函数和外部函数,函数声明在一个TU中的出现不一定需要在同一个TU中定义。这些属性的这些组合(并且只有这些)是可能的:

  • 函数标识符是用外部链接声明的,函数不是内联函数,并且是外部定义的函数出现在TU
  • 函数标识符是用外部链接声明的,函数不是内联函数,并且没有定义[=函数的 168=] 与声明一起出现在 TU 中。 如果 TU 中引用了函数标识符,则外部定义会出现在不同的 TU 中。
  • 函数标识符使用外部链接声明,函数内联函数,内联定义的函数出现在TU中。 如果 TU 中引用了函数标识符,则外部定义会出现在不同的 TU 中。
  • 函数标识符是用外部链接显式声明的,函数一个内联函数, 函数的 外部定义 出现在 TU
  • 函数标识符是用内部链接声明的,函数不是内联函数,内部定义的函数出现在TU
  • 函数标识符是用内部链接声明的,函数不是内联函数,没有定义的函数出现在TU中。 该 TU 中从未引用过函数标识符。
  • 函数标识符是用内部链接声明的,函数一个内联函数,一个内联定义的函数出现在TU

在给定 TU 中使用外部链接声明的函数标识符指的是外部函数定义,它可能出现在不同的 TU 中。

在给定 TU 中使用内部链接声明的函数标识符引用同一 TU 中的内部或内联函数定义。

内联函数声明可以有外部或内部链接,在任何一种情况下,该函数的内联定义必须出现在同一个 TU 中。如果函数标识符具有外部链接(在该 TU 中)和内联函数定义,则由实现自行决定是否以及在何处使用该 TU 中其他地方的内联定义或(必需的)外部定义。


更新:

经过深思熟虑,您将函数本身描述为 "inline functions" 和 "extern inline functions" 似乎反映了函数的内联字符在全局范围内 与函数的标识符相关联(例如 fun1),至少对于具有外部链接的标识符。事实并非如此,正如我希望我相当冗长的话语所传达的那样。

函数标识符的内联字符是每个 TU 属性,函数定义的内联字符是单独的每个定义 属性。如果在任何 TU 中将给定函数声明为内联函数,则必须在该 TU 中提供该函数的定义。来自不同 TU 的函数的外部定义不满足该要求,即使该函数在定义出现的 TU 中被声明为内联函数。