有一个约束6.7.4(p3)
:
与外部链接的函数的内联定义不得 包含具有静态或线程的可修改对象的定义 存储持续时间,不得包含对标识符的引用 与内部链接。
考虑以下示例:
static const int i = 10;
void do_print(void);
inline void do_print(void){
printf("%d/n", i); //Reference to an identifier with internal linkage
//constraint violation
}
演示
在这里,使用外部链接的函数的内联定义使用具有内部链接的标识符。因此,根据5.1.1.3(p1)
:
符合实现应至少产生一个诊断消息(以实现定义的方式识别( 预处理翻译单元或翻译单元包含一个 即使行为是 也明确指定为未定义或实现定义的。
我期望编译器以某种方式报告违反此约束的行为(有些警告(。但是,该代码可以很好地编译,没有警告或其他消息。
问题是:为什么在上面的约束违规时不会产生诊断消息?
问题是:为什么在上面的约束违规情况下不会产生诊断消息?
因为您的编译器在这方面不合格。
这实际上就是全部。您已经正确分析了标准的文本,并将其正确应用于呈现的代码。一个符合的实现必须通过do_print
的内联实现来发出有关对变量i
的引用的诊断。不符合不合格的实现。
i在这一点上指出,某些编译器以这种一般方式不合格 - 默认情况下省略了所需的诊断,同时提供了打开这些强制性诊断的选项。例如,这是GCC中-pedantic
选项的功能。但是,我发现即使指定了-pedantic
,我的GCC的(有些过时的(版本也不会警告您的代码。
cppreference有一个段落,解释了其背后的理由:
如果在某些翻译单元中声明了一个函数,则无需在任何地方声明它:最多只能提供一个翻译单元,也可以提供常规的,非内线的非静态功能,或将函数声明为外部内线。据说这个翻译单元提供了外部定义。如果在表达式中使用了外部链接的函数的名称,则必须存在一个外部定义,请参见一个定义规则。
如果外部定义存在于程序中,则该函数的地址始终是外部函数的地址,但是当使用此地址进行函数调用时,未指定是否为inline定义(如果在翻译中存在单位(或外部定义。
笔记也说(强调我的(:
内联关键字是从C 采用的,但是在C 中,如果在每个翻译单元中声明函数,则必须在每个翻译单元中声明它,并且内联函数的每个定义都必须完全相同( inc,只要程序的行为不取决于差异(。另一方面,C 允许非const函数 - 本地静电史,并且来自内联函数的不同定义的所有功能 - 本地静态在C 中都是相同的,但在C。
中是不同的。
这意味着,如果本地内联函数在一个翻译单元中使用 static const value
,则可以在静态const变量的不同转换单元中定义具有相同名称的非内联函数未指定编译器是否将使用全局非内线版本的本地内联。