繁体   English   中英

在块范围内使用extern

[英]Use of extern in block scope

clang,gcc和VS2013都抱怨在main()重新定义w ,但我在标准中找不到任何禁止它的东西。

namespace N {
    extern int j;
    int j;
}

int main()
{
    extern int w;
    int w;
}

这些段落说明了在块作用域中使用extern声明,但它们似乎不能证明错误消息的合理性:

§3.3.1/ 4

给定一个声明区域中的一组声明,......

[注意:这些限制适用于引入名称的声明性区域,该名称不一定与声明发生的区域相同。 特别是,详细类型说明符(7.1.6.3)和友元声明(11.3)可能会将一个(可能不可见)名称引入封闭的名称空间中; 这些限制适用于该地区。 本地extern声明(3.5)可能会在声明出现的声明区域中引入一个名称,并在一个封闭的命名空间中引入一个(可能不可见)名称 ; 这些限制适用于这两个地区。 - 尾注]

§3.3.2/ 10

[注意:Friend声明引用的函数或类是最近的封闭命名空间的成员,但它们不会在该命名空间中引入新名称(7.3.1.2)。 块作用域中的函数声明和使用块作用域中的extern说明符的变量声明引用作为封闭命名空间成员的声明,但它们不会在该作用域中引入新名称 - 尾注]

我认为这主要由§3.5/ 6涵盖。

特别是:

在块作用域中声明的函数的名称和由块作用域extern声明声明的变量的名称具有链接。 如果存在具有相同名称和类型的链接的实体的可见声明,忽略在最内部封闭命名空间范围之外声明的实体,则块范围声明声明该实体并接收先前声明的链接。 如果存在多个这样的匹配实体,则该程序是不正确的。 否则,如果未找到匹配的实体,则块范围实体接收外部链接。

所以, extern int w; 声明一个具有链接的w (外部链接,在这种情况下,因为此时没有匹配的实体可见)。

然后你尝试定义一个没有链接的本地w (§3.5/ 8)。

这在相同的范围内给出了两个相同名称的声明,但具有不同的链接。 这是§3.3.1/ 4所禁止的:

给定一个声明区域中的一组声明,每个声明区域指定相同的非限定名称,

  • 它们都应指同一实体,或全部指功能和功能模板; 要么
  • 正好一个声明应声明一个不是typedef名称的类名或枚举名,其他声明都应引用相同的变量或枚举,或者全部引用函数和函数模板; 在这种情况下,隐藏类名或枚举名(3.3.10)。

两者都没有引用函数,函数模板,类名或枚举名,因此这些“转义子句”都不适用。 这两个声明必须引用同一个实体,该实体必须同时具有外部链接和无链接。 由于这是不可能的,代码是不正确的。

以下是我的解释:在§3.3.1/ 3中,标准说:

声明声明的名称被引入声明发生的范围,除了友元说明符(11.3)的存在,详细类型说明符(7.1.6.3)的某些用法和使用指令(7.3) .4)改变这种一般行为。

由于extern声明未列为异常,因此在块作用域中引入了该名称,这就是您尝试重新声明它时出现错误的原因。

你引用的段落说

但他们没有在该范围内引入新名称。

这有点模棱两可,因为提到了块范围和命名空间范围。 如果标准引用了块范围,那么标准就会自相矛盾,因此我假设命名空间范围是指。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM