?
このドキュメントでは、 php中國(guó)語(yǔ)ネットマニュアル リリース
當(dāng)在C程序中遇到標(biāo)識(shí)符時(shí),執(zhí)行查找以找到引入該標(biāo)識(shí)符的聲明,該聲明當(dāng)前處于范圍內(nèi)。如果這些標(biāo)識(shí)符屬于不同的類別(稱為名稱空間),那么C允許同一標(biāo)識(shí)符的多個(gè)聲明同時(shí)處于同一范圍內(nèi):
1)標(biāo)簽名稱空間:將所有標(biāo)識(shí)符聲明為標(biāo)簽。
2)標(biāo)簽名稱:聲明為結(jié)構(gòu)名稱,聯(lián)合和枚舉類型的所有標(biāo)識(shí)符。請(qǐng)注意,所有三種標(biāo)簽共享一個(gè)名稱空間。
3)成員名稱:聲明為任何一個(gè)結(jié)構(gòu)或聯(lián)合的成員的所有標(biāo)識(shí)符。每個(gè)結(jié)構(gòu)和聯(lián)合都引入了它自己的這種名稱空間。
4)所有其他標(biāo)識(shí)符,稱為普通標(biāo)識(shí)符以區(qū)分(1-3)(函數(shù)名稱,對(duì)象名稱,typedef名稱,枚舉常量)。
在查找時(shí),標(biāo)識(shí)符的名稱空間由其使用方式?jīng)Q定:
1)在標(biāo)簽名稱空間中查找作為goto語(yǔ)句的操作數(shù)出現(xiàn)的標(biāo)識(shí)符。
2)隨后的關(guān)鍵字標(biāo)識(shí)符struct
,union
或enum
在標(biāo)簽名稱空間中查找。
3)通過(guò)指針操作符訪問(wèn)成員訪問(wèn)或成員訪問(wèn)之后的標(biāo)識(shí)符在由成員訪問(wèn)操作符的左操作數(shù)確定的類型的成員的名稱空間中查找。
4)在普通標(biāo)識(shí)符的名稱空間中查找所有其他標(biāo)識(shí)符。
宏的名稱不是任何名稱空間的一部分,因?yàn)樗鼈冊(cè)谡Z(yǔ)義分析之前被預(yù)處理器替換。
通常的做法是使用typedef聲明將struct / union / enum名稱注入普通標(biāo)識(shí)符的名稱空間中:
struct A { }; // introduces the name A in tag name spacetypedef struct A A; // first, lookup for A after "struct" finds one in tag name space // then introduces the name A in the ordinary name spacestruct A* p; // OK, this A is looked up in the tag name spaceA* q; // OK, this A is looked up in the ordinary name space
跨兩個(gè)名稱空間使用相同標(biāo)識(shí)符的著名示例是stat
POSIX標(biāo)頭中的標(biāo)識(shí)符sys/stat.h
。它用作普通標(biāo)識(shí)符時(shí)指定一個(gè)函數(shù),并在用作標(biāo)記時(shí)指示一個(gè)結(jié)構(gòu)體。
與C ++不同,枚舉常量不是結(jié)構(gòu)成員,它們的名稱空間是普通標(biāo)識(shí)符的名稱空間,并且由于C中沒(méi)有結(jié)構(gòu)作用域,因此它們的作用域是結(jié)構(gòu)聲明出現(xiàn)的范圍:
struct tagged_union { enum {INT, FLOAT, STRING} type; int integer; float floating_point; char *string;} tu; tu.type = INT; // OK in C, error in C++
void foo (void) { return; } // ordinary name space, file scopestruct 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}
C11 standard (ISO/IEC 9899:2011):
6.2.3 Name spaces of identifiers (p: 37)
C99 standard (ISO/IEC 9899:1999):
6.2.3 Name spaces of identifiers (p: 31)
C89/C90 standard (ISO/IEC 9899:1990):
3.1.2.3 Name spaces of identifiers