我正在努力理解C++中的存储类说明符。我有两个箱子。
这里,在给定的相同范围内,声明相同的变量名称。
情况1:
#include <iostream>
static int i;
extern int i;
int main() {
std::cout<<i<<std::endl;
return 0;
}
输出:
0
情况2:
#include <iostream>
extern int i;
static int i;
int main() {
std::cout<<i<<std::endl;
return 0;
}
出现错误:
prog.cpp:4:12: error: 'i' was declared 'extern' and later 'static' [-fpermissive]
static int i;
^
prog.cpp:3:12: note: previous declaration of 'i'
extern int i;
为什么第一种情况很好,而第二种情况会出错
extern
有点特殊,因为用它标记的声明会查找同一实体的前一个声明,如果找到了,则使用前一个链接。只有当它找不到一个实体时,它才会声明一个具有外部链接的新实体。
另一方面,static
无条件地声明其具有内部链接的实体。
这意味着这段代码只是用内部链接来声明和定义i
。第二个声明查找第一个并重用其链接。
static int i;
extern int i;
而这段代码声明变量具有外部链接,然后声明并定义变量具有内部链接,这是一个错误。
extern int i;
static int i;
这种行为的原因很难追踪,但最有可能追溯到C.标准前的日子
在C++中,这种行为由最新草案N4687:中的[basic.link],6.5/6指定
在块作用域中声明的函数的名称和由块作用域外部声明声明的变量的名称具有链接。如果存在具有相同名称和类型链接的实体的可见声明,忽略在最内部封闭命名空间范围之外声明的实体,则块范围声明声明相同实体并接收上一声明的链接。如果存在不止一个这样的匹配实体,则程序是格式错误的。否则,如果没有找到匹配的实体,块作用域实体将接收外部链接。