我试图详细了解静态和外部函数之间的区别。
我知道静态和外部内联函数之间的基本区别。
如果错误,请纠正我的理解:
下面是一个示例代码,我对此行为感到困惑。
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++);
}
}
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++);
}
}
file.h
#ifndef FILE_H
#define FILE_H
extern inline void fun1(void);
#endif
当我编译上面的代码&#34; gcc file1.c file2.c&#34;时,从file2.c调用了fun1。这很清楚,因为fun1被声明为extern,它应该采用file2.c中的extern函数(默认情况下所有内联函数都是extern?)。
但是当我在file1.c中将静态内联函数更改为静态函数(static void fun1(void))时,从file1.c调用了fun1。可能是什么原因?
我也读过&#34;如果内联函数声明了外部链接但未在同一个翻译单元中定义,则行为未定义&#34;。但我不明白这一点。这可以用上面的例子来解释吗?
与C相比,C ++中的静态函数和外部函数之间是否存在差异?
答案 0 :(得分:4)
您的代码不正确,因为您无法使用extern
(默认值)声明函数,然后提供static
定义。它完全编译的事实并不表示任何有用的东西。
从n1548§6.2.2:
如果在翻译单元中,同一标识符同时显示内部和外部链接,则行为未定义。
所以,你在file1.c
中得到类似的东西:
// Has external linkage (which is the default!)
extern inline void fun1(void);
// This would also have external linkage.
inline void fun1(void);
// This has static linkage.
static inline void fun1(void) {
...
}
(注意:“外部链接”是默认值,但extern inline
实际上意味着特殊内容,它与inline
不同。)
的Bam!未定义的行为。编译器甚至可能不会给你一个错误信息,虽然有些编译器似乎给出了错误信息。
error: static declaration of 'func' follows non-static declaration
此错误实际上 nothing 与函数为inline
的事实有关。带或不带inline
的错误。
静态内联函数仅对定义它的翻译单元可见。
所有static
函数都是如此。它们具有“内部链接”,因此您可以在一个文件中使用static void func(void);
,在另一个文件中使用完全不同的static int func(char *p);
。 inline
在这里没有任何区别。
extern内联函数可以在多个翻译单元中访问。
是的,这就是为什么你不应该把它们放在头文件中。如果将它们放在头文件中,您将获得同一函数的多个不同定义,这些定义都可以从不同的转换单元访问。这是一个错误。相反,将extern inline
放在源文件中,但它只需要是声明,而不是定义。
最好在头文件中定义内联函数
在其他地方定义内联函数没有任何意义。如果您的函数仅在一个文件中使用,则只需标记static
,编译器将决定如何调用该函数。
静态和静态内联函数定义之间没有区别。
是的,没有区别。
嗯,从技术上讲,不,这是有区别的,因为允许编译器以static inline
函数的方式处理static
函数。但是,现代编译器倾向于使用自己的一组规则来决定内联函数,函数是否inline
不会对该过程产生太大影响。
嗯,实际上还有另外一个区别。如果未使用static inline
函数定义,则不会在GCC中生成警告,但static
函数将会生成警告。这样您就可以在头文件中放置static inline
函数。这是将inline
放在头文件中的替代方法,这需要您在程序中的某处为该函数设置extern inline
。但是,如果编译器决定不想内联你的static inline
函数,或者因为它认为内联更糟或者因为内联是不可能的,那么它将不得不在每个文件中单独复制该函数。用于。
如果函数static
具有先前的非静态声明,则不要声明它。这是一个错误,即使它编译。</ p>
不要在头文件中声明inline extern
函数。这为函数创建了一个“外部定义”,您只能在整个程序中使用其中一个。
在未定义头文件的情况下,不要在头文件中声明inline
个函数。没有意义。
以下是您希望如何执行此操作的方法:
在mylib.h
:
// Provide "inline definition" of the function.
inline int times_two(int x) {
return x * 2;
}
在mylib.c
:
#include "mylib.h"
// Provide "external definition" of the function.
extern inline int times_two(int x);
这是自C99以来做事的标准方法。编译器应该可以自由地使用内部定义或外部定义,无论它认为哪个更好。如果您没有外部定义或者您有多个外部定义,则可能会出现链接错误,就像使用常规函数一样。
C ++对内联函数有着完全不同的规则。