我试图理解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;
为什么第一种情况正常,而第二种情况却出错?
答案 0 :(得分:13)
extern
有点特殊,因为标有它的声明会查找同一实体的先前声明,如果找到一个声明,它会使用之前的链接。只有当它没有找到它时才会声明一个具有外部链接的新实体。
static
无条件地声明其实体具有内部联系。
这意味着此代码仅使用内部链接声明和定义i
。第二个声明找到第一个并重新使用它的链接。
static int i;
extern int i;
此代码声明变量具有外部链接,然后声明并定义它以具有内部链接,这是一个错误。
extern int i;
static int i;
这种行为的原因很难跟踪,但最有可能回到C标准前的日子。
在C ++中,此行为由[basic.link]指定,最新草案N4687中为6.5 / 6:
块作用域中声明的函数的名称和块作用域extern声明声明的变量的名称具有链接。如果存在具有相同名称和类型的链接的实体的可见声明,忽略在最内部封闭命名空间范围之外声明的实体,则块范围声明声明该实体并接收先前声明的链接。如果存在多个这样的匹配实体,则该程序是不正确的。否则,如果未找到匹配的实体,则块范围实体将接收外部链接。