【发布时间】:2018-05-30 06:45:54
【问题描述】:
我用-std=c++11 -Wall 用g++ (7.1) 和clang++ (xcode 9.0) 编译了以下程序并得到了结果:
g++
0x10052c050
0x10052c040
0x10052c040
叮当++
0x108b74024
0x108b74018
0x108b74018
表示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;
}
但是,在 C++11 [3.9/6] 中:
...数组对象的声明类型可能是一个未知大小的数组,因此在翻译单元中的某一点是不完整的,稍后会完成;这两个点的数组类型(“T 的未知边界数组”和“N T 的数组”)是不同的类型。 ...
int a[3];和int a[];是不同的类型,
在 C++11 [3.5/6] 中:
如果存在具有相同名称和类型的链接的实体的可见声明,忽略在最内层封闭命名空间范围之外声明的实体,块范围声明声明相同的实体并且接收前一个声明的链接。如果有多个这样的匹配实体,则程序是非良构的。 否则,如果没有找到匹配的实体,则块范围实体接收外部链接。
“同名同类型”不兼容,所以extern int a[];不会收到之前声明的链接(static int a[3];),
因此,“否则,如果没有找到匹配的实体,则块范围实体接收外部链接。”兼容。
我的问题是:
- 为什么编译的结果与C++11标准的写法不一致?
- 或者如果我的理解是错误的,那是对的?
注意:这个问题不同于error: extern declaration of 'i' follows declaration with no linkage
【问题讨论】:
-
可能因为
a被 odr-used 用于不完整的类型,所以程序格式不正确;不需要诊断,因此有奇怪的行为? -
@xskxzr 是的,我已经编辑过了,谢谢。
标签: c++ c++11 language-lawyer linkage