在C++中extern声明"T的未知数组"

che*_*ing 8 c++ linkage language-lawyer c++11

我使用g ++(7.1)和clang ++(xcode 9.0)编译了以下程序-std=c++11 -Wall并获得结果:

克++

0x10052c050
0x10052c040
0x10052c040
Run Code Online (Sandbox Code Playgroud)

铛++

0x108b74024
0x108b74018
0x108b74018
Run Code Online (Sandbox Code Playgroud)

这意味着extern int a[];static int a[3];声明相同的实体并具有相同的链接(内部链接).

//a.cpp
#include <stdio.h>
int a[3];
void f()
{
    printf("%p\n", (void*)a);
};
//b.cpp
extern void f();
static int a[3];
void g()
{
    printf("%p\n", (void*)a);
    extern int a[];
    printf("%p\n", (void*)a);
}
int main(int argc, char* argv[])
{
    f();
    g();
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

但是,在C++ 11 [3.9/6]中:

...数组对象的声明类型可能是一个未知大小的数组,因此在翻译单元的某一点不完整,稍后会完成; 这两个点的数组类型("T的未知边界数组"和"NT数组")是不同的类型....

int a[3];并且int a[];是不同的类型,

在C++ 11 [3.5/6]中:

如果与具有相同名称和类型关联实体的可见声明,忽略了最内层的命名空间范围之内声明的实体,块范围内声明宣布,同一实体和接收与先前的声明的链接.如果存在多个这样的匹配实体,则该程序是不正确的.否则,如果未找到匹配的实体,则块范围实体接收外部链接.

"具有相同的名称和类型"不兼容,因此extern int a[];不应接收先前声明(static int a[3];)的链接,因此,"否则,如果未找到匹配的实体,则块范围实体接收外部链接."是兼容的.

我的问题是:

  • 为什么编译器的结果与C++ 11标准的措辞不一致?
  • 或者如果我的理解是错的,那是对的?

注意:这个问题与错误不同:'i'的extern声明遵循声明,没有链接

小智 0

“extern int a[]”没有完全定义“a”。

在 @Bob__ 对我的原始帖子发表评论后更新。

我在尝试过的所有三个编译器上都得到了相同的结果(直到指针地址发生变化) - 谢谢,@Bob__。既然它们都在编译,我们是否应该说是标准的语言需要更新?