C标准说:
对于使用存储类说明符extern声明的标识符 可以看到该标识符的先前声明的范围,31) 如果事先声明指定内部或外部联系,则 后面声明中标识符的链接与 在先前声明中指定的联系。如果没有事先声明 可见,或者如果先前的声明指定没有链接,那么 标识符有外部链接。
尚不清楚的是,先前要考虑的标识符是否必须具有相同的类型(注意:C ++标准明确指出“具有相同名称和类型的实体”)。例如:
static int a; // internal linkage
void f()
{
float a; // no linkage, instead of 'int a' we have 'float a'
{
extern int a; // still external linkage? or internal in this case?
a = 0; // still unresolved external?
}
}
我尝试用不同的编译器测试它,但似乎联系主题并不是一个非常团结的主题。
答案 0 :(得分:2)
C对其所有全局变量使用平面名称空间。与C ++不同,C ++需要链接器注意全局变量的类型(查找名称修改以获取更多信息),C将此要求提供给程序员。
在同一翻译单元内更改链接时,重新声明具有不同类型的变量是错误的。
我将使用你的例子添加一些小的
static int a; // internal linkage
static int b; // internal linkage
void f()
{
float a = 123.25; // this variable shadows static int a
int b = 321; // this variable shadows static int b
{ // Open a new scope, so the line below is not an illegal re-declaration
// The declarations below "un-shadow" static a and b
extern int a; // redeclares "a" from the top, "a" remains internal
extern int b; // redeclares "b" from the top, "b" remains internal
a = 42; // not an unresolved external, it's the top "a"
b = 52; // not an unresolved external, it's the top "b"
printf("%d %d\n", a, b); // static int a, static int b
}
printf("%f %d\n", a, b); // local float a, int b
}
此示例打印
42 52
123.250000 321
当您在多个翻译单元中更改类型时,C ++会在链接时捕获它,而C将链接正常,但会产生未定义的行为。