为何typedef定义的名称可作结构体成员名却不能作同作用域变量名?
关于typedef名字与结构体成员名的冲突问题解释
这是个非常细节且有意思的问题,咱们结合C99标准的名字空间规则来彻底搞清楚:
先明确三个核心案例
- 可正常编译:
typedef int blah; struct s { char blah; }; - 编译报错(重复定义冲突):
typedef int blah; char blah; - 可正常编译:
typedef int blah; struct s { blah blah; };
核心原因:C语言的「名字空间」划分
C99标准对标识符的名字空间做了明确区分,不同类别的标识符处于不同的名字空间,同一名字空间内不能出现重复定义,但不同空间的同名标识符互不干扰:
C99 6.2.3 标识符的名字空间:
标识符分为几个名字空间,如下:
- 结构体或联合体的成员;每个结构体或联合体都为其成员拥有一个单独的名字空间。
- 标签(结构体、联合体或枚举的名字)。
- 普通标识符(包括typedef定义的名字、变量名、函数名、数组名等)。
案例2报错的原因
全局作用域中,typedef int blah定义的blah属于普通标识符名字空间,后续的char blah是定义变量,同样属于普通标识符名字空间。同一作用域的同一名字空间内不允许重复定义,所以编译器会报错。
案例1通过的原因
结构体内部的成员名blah属于该结构体的成员名字空间,和全局作用域中typedef定义的blah(普通名字空间)分属不同空间,编译器能明确区分两者,因此不会产生冲突。
案例3通过的原因
在结构体内部声明成员时,名字查找优先级是先找普通名字空间:
- 第一个
blah会匹配全局的typedef定义(属于普通名字空间),被解析为int类型; - 第二个
blah是成员名,属于该结构体的成员名字空间;
两者分属不同空间,因此完全合法。
总结
typedef定义的名字并非在结构体内部不可见,而是结构体成员拥有独立的名字空间,和外部的普通标识符(包括typedef名字)互不冲突。这就是三个案例表现不同的根本原因。
内容的提问来源于stack exchange,提问作者Alex D
相关产品推荐
相关产品推荐

