簡體   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