我遇到了一个奇怪的问题,我将其范围缩小到以下测试用例:
inl.h:
inline const char *fn() { return id; }
抄送:
#include <stdio.h>
static const char *id = "This is A";
#include "inl.h"
void A()
{
printf("In A we get: %s\n", fn());
}
抄送:
#include <stdio.h>
static const char *id = "This is B";
#include "inl.h"
void B()
{
printf("In B we get: %s\n", fn());
}
extern void A();
int main()
{
A();
B();
return 0;
}
现在,当我用它编译它时,g++ -O1 a.cc b.cc
它似乎可以正常工作。我得到:
In A we get: This is A
In B we get: This is B
但如果我编译g++ -O0 a.cc b.cc
我得到:
In A we get: This is A
In B we get: This is A
请注意,我实际上是在这里尝试使用 C11 语义,但我使用的是 g++,因为 gcc 还不支持 C11。
现在据我所见,同时查看 C11 规范和 C++ 规范(C++11 和更早的规范——内联和静态全局变量的语义似乎没有改变),它应该做我想要的,使用失败-O0
是gcc中的一个错误。
这是正确的,还是我在规范中缺少某些东西会导致这种未定义的行为?
编辑
常见的答案似乎声称fn
需要声明static
它才能工作。但根据 C99 规范的 6.7.4.6(C11 规范中的 6.7.4.7——不确定 C++ 规范):
如果翻译单元中函数的所有文件范围声明都包含不带 extern 的内联函数说明符,则该翻译单元中的定义是内联定义。内联定义不为函数提供外部定义,也不禁止在另一个翻译单元中进行外部定义。
所以由于这里没有明确的extern
,这些应该是两个独立的内联函数,彼此没有交互。不需要明确static
的。
使用显式静态解决了 C 的问题,但不适用于 C++ 内联成员函数,因为static
在这种情况下关键字具有完全不同的含义。