查詢與名稱空間
來自 cppreference.com
在 C 程式中遇到識別符號時,會執行查詢以定位引入該識別符號且當前在作用域中的宣告。如果這些識別符號屬於不同的類別(稱為名稱空間),C 允許同一識別符號的多個宣告同時在作用域中。
1) 標籤名稱空間:所有宣告為標籤的識別符號。
4) 全域性屬性名稱空間:由標準或實現定義的屬性字首定義的屬性標記。
5) 非標準屬性名:跟隨屬性字首的屬性名。每個屬性字首都有一個單獨的名稱空間,用於它引入的實現定義的屬性。
|
(自 C23 起) |
6) 所有其他識別符號,稱為普通識別符號,以區別於(1-5)(函式名、物件名、typedef 名、列舉常量)。
在查詢時,識別符號的名稱空間由其使用方式決定。
1) 作為goto 語句的操作數出現的識別符號在標籤名稱空間中查詢。
2) 跟隨關鍵字struct、union或enum的識別符號在標記名稱空間中查詢。
3) 跟隨成員訪問或透過指標訪問成員運算子的識別符號,在由成員訪問運算子的左運算元確定的型別的成員名稱空間中查詢。
4) 直接出現在屬性說明符([[...]])中的識別符號在全域性屬性名稱空間中查詢。
5) 跟隨屬性字首後面的::標記的識別符號,在由該屬性字首引入的名稱空間中查詢。
|
(自 C23 起) |
6) 所有其他識別符號在普通識別符號的名稱空間中查詢。
目錄 |
[編輯] 注意
宏的名稱不屬於任何名稱空間,因為它們在語義分析之前被預處理器替換。
通常的做法是使用typedef宣告將結構體/聯合體/列舉名稱注入普通識別符號的名稱空間。
struct A { }; // introduces the name A in tag name space typedef struct A A; // first, lookup for A after "struct" finds one in tag name space // then introduces the name A in the ordinary name space struct A* p; // OK, this A is looked up in the tag name space A* q; // OK, this A is looked up in the ordinary name space
一個在兩個名稱空間中使用相同識別符號的著名例子是 POSIX 標頭檔案 sys/stat.h
中的識別符號stat。當用作普通識別符號時,它表示一個函式;當用作標記時,它表示一個結構體。
與 C++ 不同,列舉常量不是結構體成員,它們的名稱空間是普通識別符號的名稱空間,並且由於 C 中沒有結構體作用域,它們的作用域是結構體宣告出現的作用域。
struct tagged_union { enum {INT, FLOAT, STRING} type; union { int integer; float floating_point; char *string; }; } tu; tu.type = INT; // OK in C, error in C++
如果不支援標準屬性、屬性字首或非標準屬性名稱,則會忽略無效屬性本身,而不會導致錯誤。 |
(自 C23 起) |
[編輯] 示例
執行此程式碼
void foo (void) { return; } // ordinary name space, file scope struct foo { // tag name space, file scope int foo; // member name space for this struct foo, file scope enum bar { // tag name space, file scope RED // ordinary name space, file scope } bar; // member name space for this struct foo, file scope struct foo* p; // OK: uses tag/file scope name "foo" }; enum bar x; // OK: uses tag/file-scope bar // int foo; // Error: ordinary name space foo already in scope //union foo { int a, b; }; // Error: tag name space foo in scope int main(void) { goto foo; // OK uses "foo" from label name space/function scope struct foo { // tag name space, block scope (hides file scope) enum bar x; // OK, uses "bar" from tag name space/file scope }; typedef struct foo foo; // OK: uses foo from tag name space/block scope // defines block-scope ordinary foo (hides file scope) (foo){.x=RED}; // uses ordinary/block-scope foo and ordinary/file-scope RED foo:; // label name space, function scope }
[編輯] 參考
- C17 標準 (ISO/IEC 9899:2018)
- 6.2.3 識別符號的名稱空間 (p: 29-30)
- C11 標準 (ISO/IEC 9899:2011)
- 6.2.3 識別符號的名稱空間 (p: 37)
- C99 標準 (ISO/IEC 9899:1999)
- 6.2.3 識別符號的名稱空間 (p: 31)
- C89/C90 標準 (ISO/IEC 9899:1990)
- 3.1.2.3 識別符號的名稱空間
[編輯] 另請參閱
C++ 文件,關於名稱查詢
|