在内部范围中将内联函数重新声明为extern
是否合法?
下面的代码在MACRO
是否为真的情况下是否为合法C?
#if MACRO
enum { have_macro = 1 };
inline int foo(void){ return 43; }
#else
enum { have_macro = 0 };
#endif
int main()
{
if(have_macro){
extern int foo(void);
return foo();
}else
return 0;
}
extern int foo(void); //maybe instantiate
答案 0 :(得分:3)
在内部范围中将内联函数重新声明为extern是否合法?
是的,但是如果您在其他翻译单元中也没有内联地定义它,那么使用哪个是不确定的。
在类似的主题上,我可以通过在另一个文件中声明extern来与实例化的非静态内联链接吗?
否,内联函数仅对在其中声明和定义的编译单元可见。
6.7.4函数说明符
- 任何具有内部链接的函数都可以是内联函数。 对于具有外部链接的功能, 适用以下限制:如果函数是用内联函数说明符声明的,则它将 如果函数中的所有文件范围声明都在 一个翻译单元包括没有extern的内联函数说明符,然后是其中的定义 翻译单元是内联定义。 内联定义不提供外部定义 该功能,并且不禁止在另一个翻译单元中使用外部定义。内联 定义提供了外部定义的替代方法,翻译人员可以使用它来实现 在同一翻译单元中对函数的任何调用。不确定是否对函数进行调用 使用内联定义或外部定义。
答案 1 :(得分:3)
非语言律师的初步说明:C中的术语外部定义不应与extern
或外部链接混淆。粗略地讲,它意味着“出现在文件范围而不是内联定义的任何定义”。例如,静态函数定义将是外部定义。有关更详细的介绍,请参见C17标准的6.9节。
还请注意,内联定义一词有其独特之处;带有inline
关键字的函数定义可以是内联定义或外部定义,具体取决于我将在下面介绍的其他内容。
对于以下代码(由MACRO
定义):
inline int foo(void){ return 43; }
int main()
{
if(1){
extern int foo(void);
return foo();
}else
return 0;
}
extern int foo(void);
第一行提供foo
的外部定义,而不是内联定义:
规则是,如果存在具有inline
关键字的具有外部链接的函数的定义,和该函数的文件范围声明不包含{{1} }关键字,则函数定义是外部定义。几乎所有的确切示例,请参见C17 6.7.4 / 10。块范围声明没有区别。
到目前为止,此代码还可以,但是,如果另一个翻译单元也为inline
提供了外部定义,则将是未定义的行为。
对于没有MACRO的版本:
foo
到目前为止,这段代码还不错,但是如果某个地方程序中没有int main()
{
if(0){
extern int foo(void);
return foo();
}else
return 0;
}
extern int foo(void);
函数的一个确切定义,那将是未定义的行为。 (C17 6.9 / 5)隐藏在foo
后面的代码并没有脱离一个定义规则。
答案 2 :(得分:-1)
inline
在语言语法级别没有任何作用,它不会更改功能签名,链接或可见性。
extern
是一个声明,您必须使用与定义相同的签名来声明该函数。 inline
不会影响功能签名和可见性,只有static
会影响功能签名和可见性。
只要您在同一翻译单元中没有违反one definition rule,就可以了。如果多个单元输出相同的弱定义,则在链接或加载时随机选择一个。