繁体   English   中英

将非静态内联函数重新声明为extern

[英]Redeclaring a non-static inline function as extern

在内部作用域中将内联函数重新声明为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

在内部作用域中将内联函数重新声明为extern是否合法?

是的,但是如果您在其他翻译单元中也没有内联地定义了它,那么使用哪个是不确定的。

在类似的主题上,是否可以通过在另一个文件中声明extern来与实例化的非静态内联链接?

不,内联函数仅对在其中声明和定义的编译单元可见。

6.7.4功能说明符

  1. 具有内部链接的任何功能都可以是内联功能。 对于具有外部链接的功能,适用以下限制:如果使用内联功能说明符声明功能,则还应在同一转换单元中定义该功能。 如果翻译单元中某个函数的所有文件范围声明都包含不带extern的内联函数说明符,则该翻译单元中的定义为内联定义。 内联定义不为函数提供外部定义,也不禁止在另一个翻译单元中使用外部定义。 内联定义提供了外部定义的替代方法,翻译器可以使用该替代方法在同一翻译单元中实现对该函数的任何调用。 未指定对函数的调用是使用内联定义还是使用外部定义。

非语言律师的初步说明:术语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关键字, 该函数的文件范围声明没有inline关键字,则函数定义为外部定义。 几乎所有的确切示例,请参见C17 6.7.4 / 10。 块范围声明没有区别。

到目前为止,此代码还可以,但是如果另一个翻译单元还为foo提供了外部定义,则该行为将是未定义的行为。


对于没有MACRO的版本:

int main()
{
    if(0){
        extern int foo(void);
        return foo();
    }else
        return 0;
}
extern int foo(void);

到目前为止,这段代码还不错,但是如果程序中某个地方没有foo函数的确切定义,那将是未定义的行为。 (C17 6.9 / 5)将代码隐藏在if(0)后面并不能脱离一个定义规则。

inline在语言语法级别不执行任何操作,它不会更改功能签名,链接或可见性。

extern是一个声明,必须使用与定义相同的签名声明该函数。 inline不会影响函数签名,只有static会影响可见性。

只要您不违反同一翻译单元中的一个定义规则 ,就可以了。 如果多个单元输出相同的弱定义,则在链接或加载时随机选择一个。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM