在C ++中的给定相同范围内声明相同的变量名称

时间:2017-10-16 06:53:46

标签: c++ variables storage one-definition-rule

我试图理解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;

为什么第一种情况正常,而第二种情况却出错?

1 个答案:

答案 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声明声明的变量的名称具有链接。如果存在具有相同名称和类型的链接的实体的可见声明,忽略在最内部封闭命名空间范围之外声明的实体,则块范围声明声明该实体并接收先前声明的链接。如果存在多个这样的匹配实体,则该程序是不正确的。否则,如果未找到匹配的实体,则块范围实体将接收外部链接。