C中的静态和外部内联函数

Sal*_*lim 5 c

我试图详细了解静态和外部函数之间的区别.

我知道静态和外部内联函数之间的基本区别.

如果错误,请纠正我的理解:

  • 静态内联函数仅对定义它的转换单元可见.
  • extern内联函数可以在多个翻译单元中访问.
  • 最好在头文件中定义内联函数
  • 静态和静态内联函数定义之间没有区别.

下面是一个示例代码,我对此行为感到困惑.

在file1.c

#include <stdio.h>
#include "file.h"

int main(void)
{
  fun1(); 
  return 0;  
}

static inline void fun1(void)
{
  int i;
  for (i = 0; i < 10; i++) {
      static int k = 20;
      printf("Value : %d \n", k++);
  }
}
Run Code Online (Sandbox Code Playgroud)

file2.c中

#include <stdio.h>

inline void fun1(void)
{
  int i;
  int k = 0;
  for (i = 0; i < 10; i++) {
      printf("Value : %d \n", k++);
  }
}
Run Code Online (Sandbox Code Playgroud)

file.h

#ifndef FILE_H
#define FILE_H 

extern inline void fun1(void);

#endif
Run Code Online (Sandbox Code Playgroud)

当我编译上面的代码"gcc file1.c file2.c"时,从file2.c调用了fun1.这很明显,因为fun1被声明为extern,它应该采用file2.c中的extern函数(默认情况下所有内联函数都是extern?).

但是当我在file1.c中将静态内联函数更改为静态函数(static void fun1(void))时,从file1.c调用了fun1.可能是什么原因 ?

我还读到"如果内联函数声明了外部链接但未在同一翻译单元中定义,则行为未定义".但我不明白这一点.这可以用上面的例子来解释吗?

与C相比,C++中的静态和外部函数有什么区别吗?

Die*_*Epp 4

extern您的代码不正确,因为您无法使用(默认情况下)声明函数并随后提供static定义。它能编译的事实并不表明有什么用处。

\n\n

从n1548 \xc2\xa76.2.2:

\n\n
\n

如果在翻译单元内,相同的标识符同时出现在内部和外部链接中,则行为未定义。

\n
\n\n

所以,你会得到这样的东西file1.c

\n\n
// Has external linkage (which is the default!)\nextern inline void fun1(void);\n\n// This would also have external linkage.\ninline void fun1(void);\n\n// This has static linkage.\nstatic inline void fun1(void) {\n    ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

(注意:“外部链接”是默认值,但extern inline实际上意味着一些特殊的东西,它与 不同inline。)

\n\n

嘭!未定义的行为。编译器甚至可能不会给您错误消息,尽管有些编译器似乎会为此提供错误消息。

\n\n
\n错误: \'func\' 的静态声明遵循非静态声明\n
\n\n

这个错误实际上与该函数是无关inline。无论有或没有,这都是一个错误inline

\n\n

那些问题呢?

\n\n
\n

静态内联函数仅对定义它的翻译单元可见。

\n
\n\n

所有函数都是如此static。它们具有“内部链接”,因此您可以将其放在static void func(void);一个文件中,而将完全不同的文件static int func(char *p);放在另一个文件中。这里没有inline区别。

\n\n
\n

外部内联函数可以在多个翻译单元中访问。

\n
\n\n

是的,这就是为什么您不应该将它们放入头文件中。如果将它们放入头文件中,您将获得同一函数的多个不同定义,这些定义都可以从不同的翻译单元访问。这是一个错误。相反,将其放入extern inline源文件中,但它只需要是声明,而不是定义。

\n\n
\n

最好在头文件中定义内联函数

\n
\n\n

在其他地方定义内联函数没有任何实际意义。如果您的函数仅在一个文件中使用,只需标记它static,编译器将决定如何调用该函数。

\n\n
\n

静态和静态内联函数定义之间没有区别。

\n
\n\n

是的,没有区别。

\n\n

static inline好吧,从技术上讲,不,这是有区别的,因为允许编译器以不同于函数的方式对待函数static。然而,现代编译器倾向于决定使用自己的一组规则来内联函数,并且函数是否内联inline并不会对该过程产生太大影响。

\n\n

嗯,实际上还有另一个区别。如果不使用函数static inline定义,则不会在 GCC 中生成警告,但函数static会生成警告。这样您就可以将static inline函数放入头文件中。这是放入头文件的替代方法inline,头文件要求您extern inline在程序中的某个位置有一个用于该函数的函数。但是,如果编译器决定不内联您的static inline函数,或者因为它认为内联更糟糕,或者因为内联是不可能的,那么它必须在每个文件中制作该函数的单独副本。 s 用于.

\n\n

那么,如何正确地做到这一点呢?

\n\n

static如果函数之前有非静态声明,则切勿声明该函数。即使编译通过,这也是一个错误。

\n\n

不要inline extern在头文件中声明函数。这会为该函数创建一个“外部定义”,并且您在整个程序中只能拥有其中之一。

\n\n

不要inline在头文件中声明函数而不定义它们。无关紧要。

\n\n

以下是您想要执行此操作的方式:

\n\n

mylib.h

\n\n
// Provide "inline definition" of the function.\ninline int times_two(int x) {\n    return x * 2;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

mylib.c

\n\n
#include "mylib.h"\n\n// Provide "external definition" of the function.\nextern inline int times_two(int x);\n
Run Code Online (Sandbox Code Playgroud)\n\n

这是自 C99 以来的标准处理方式。编译器应该可以自由使用内部定义或外部定义,无论它认为哪一个更好。如果您没有外部定义或有多个外部定义,则可能会出现链接错误,就像常规函数一样。

\n\n

C++ 对于内联函数有自己完全不同的规则。

\n