查找与命名空间
来自 cppreference.cn
在 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++ 文档,关于名称查找
|