Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么内联函数需要static关键字?_C_Static_Inline - Fatal编程技术网

为什么内联函数需要static关键字?

为什么内联函数需要static关键字?,c,static,inline,C,Static,Inline,如果我试图编译以下C代码而不声明函数static,则会出现链接器错误: undefined reference to '_fun' 但如果我不让它静止,它就会工作。在C++中,它没有引用静态< /COD>关键字.< /P> // Doesn't work inline int fun() { return 3; } // Works static inline int fun() { return 3; } int main(int argc, const char * a

如果我试图编译以下C代码而不声明函数static,则会出现链接器错误:

undefined reference to '_fun'
但如果我不让它静止,它就会工作。在C++中,它没有引用<代码>静态< /COD>关键字.< /P>
// Doesn't work
inline int fun()
{
    return 3;
}

// Works
static inline int fun()
{
    return 3;
}

int main(int argc, const char * argv[])
{
    printf("%i", fun());
}

ISO C标准第6.7.4节定义了C中的内联<代码>要求。引用

任何具有内部链接的函数都可以是内联函数。暂时 与外部联动装置一起运行时,以下限制适用:如果 函数是用内联函数说明符声明的,然后 也应在同一翻译单位中定义。如果所有文件 翻译单元中函数的范围声明包括 内联函数说明符不带外部,则该 翻译单元是一个内联定义。一 内联定义不为提供外部定义 函数,并且不禁止另一个函数中的外部定义 翻译股。内联定义提供了 外部定义,翻译器可以使用它来实现任何调用 同一翻译单元中的函数。没有具体说明 对函数的调用是使用内联定义还是 外部定义

据我所知,您的定义满足所有这些要求。这:

inline int fun()
{
    return 3;
}
fun
的声明和定义。如果没有
inline
关键字,它将具有外部链接

棘手的部分是最后一句话:

未指定对函数的调用是否使用内联 定义或外部定义

在这种情况下,没有外部定义。您没有说明正在使用的编译器,但是默认情况下,
gcc-std=c99-pedantic
显然选择使用外部定义,并且由于没有外部定义,因此会出现链接器错误。(如果没有
-std=c99-pedantic
,则不会出现链接器错误,但这是因为gcc还将
内联
作为C90之上的扩展实现。)

如果您只打算在一个源文件中使用该函数,那么您也可以添加
static
关键字,为其提供内部链接

实验表明,如果我使用
-O1
-O2
-O3
中的任何一种进行优化编译,您的程序就能正确编译、链接和运行

C标准中的脚注似乎暗示gcc的行为是正确的。同一节中的示例具有类似的非静态
内联
函数定义:

inline double cels(double t)
{
      return (5.0 * (t - 32.0)) / 9.0;
}
其次是:

由于cels具有外部链接并被引用,因此 定义必须出现在另一个翻译单元中(见6.9); 内联定义和外部定义是截然不同的 任何一个都可以用于呼叫

该标准的意图似乎是,如果
内联
函数具有内部链接,则应在使用它的源文件中仅定义一次,但如果它具有外部链接,则内联定义是必须出现在其他位置的非内联定义的替代。是调用外部函数还是扩展内联定义的选择权留给了编译器

一些与您的问题不直接相关的要点:

int-fun()
可能应该是
int-fun(void)
。空括号是合法的,但它们表示函数接受未指定数量和类型的参数。
void
指定它不接受参数,这是您想要的

如果要调用
print
f,则需要
#包括
;这不是可选的


argv
的声明中不需要
const
。就这一点而言,由于您没有引用命令行参数,因此可以编写
intmain(void)
C99
inline
语义非常微妙-事实上,语言的整个部分(存储持续时间与链接、暂定定义和内联定义)都是一团糟

虽然
inline
在包含存储类说明符(
static
extern
)的定义中充当编译器提示,基本上可以忽略,但如果不存在说明符,语义会发生变化

inline int fun(void){…}
这样的定义有两个作用:

首先,它声明具有外部链接的标识符,而不提供相应的外部定义。这意味着这样的定义必须由不同的翻译单位提供,否则我们最终会出现未定义的行为(可能表现为链接失败)

第二,它提供了一个内联定义,这是外部定义的一种替代方法。由于函数体在当前翻译单元中可见,编译器可以使用它来内联函数或进行类型专门化

为了得到外部定义,直到,我认为有必要在另一个翻译单元中重复函数定义(或者用4行预处理器代码假装)

但是,这并不是必需的:一行代码——包含
extern
说明符的函数的重新声明——就足以将内联定义转换为外部定义

在你的例子中,这意味着

inline int foo(void)
{
    return 42;
}
导入头文件
foo.h
,并提供包含内容的源文件
foo.c

#include "foo.h"

// force definition to be external instead of inline
// I believe inline could be omitted, but it doesn't hurt
extern inline foo(void);
这为什么有用?由于C缺乏模板,泛型代码通常会带来性能损失,因为您需要使用
void*
和函数指针(或者在更复杂的情况下,使用vtables)伪造泛型

然而,一个足够聪明的优化器可以获得模板的大部分(可能全部)性能优势,但是(在没有链接时间优化的情况下)只有在