C:类型定义的名称空间是什么?

C:类型定义的名称空间是什么?,c,C,typedef名称在哪个名称空间中?考虑这个代码: #include <stdio.h> typedef struct x { // 'x' in tag name space int x; // 'x' in member name space int y; } x; // ?? int main() { x foo = { 1, 2 }; int x = 3; // 'x' in

typedef名称在哪个名称空间中?考虑这个代码:

#include <stdio.h>

typedef struct x {   // 'x' in tag name space
   int x;            // 'x' in member name space
   int y;
} x;                 // ??

int main() {
   x foo = { 1, 2 };
   int x = 3;        // 'x' in ordinary identifier name space

   printf("%d %d %d\n", foo.x, foo.y, x);
}

执行第二行时,标识符x在范围内,并且逻辑上应该在“普通标识符”命名空间中。此时似乎没有新的作用域,因为第1行和第2行之间没有大括号。所以第二个x不能隐藏第一个x,第二个x出错了。这个论点的缺陷是什么?这如何适用于x案例?我的假设是,该缺陷是类型名称以某种方式有一个不同的不明显的名称空间,因此这个问题的标题。

它不是由于名称空间而起作用的。新的类型名称和变量标识符位于同一个普通名称空间中,而是由于作用域

6.2.1标识符的范围

对于标识符指定的每个不同实体 标识符是可见的,即只能在 程序文本称为其作用域。委员会指定的不同实体 同一标识符要么具有不同的作用域,要么具有不同的名称 空间。有四种作用域:函数、文件、块和 功能原型。函数原型是一个函数的声明 声明其参数类型的函数

每个其他标识符的作用域由 它在声明符或类型说明符中的声明。如果声明器 或声明标识符的类型说明符出现在任何 块或参数列表,标识符具有文件范围,其中 在翻译单元的末尾终止。如果声明器或 声明标识符的类型说明符出现在块或 在函数定义中的参数声明列表中, 标识符具有块作用域,该作用域终止于 关联块。如果声明 标识符显示在中的参数声明列表中 函数原型不是函数定义的一部分,标识符 具有函数原型作用域,该作用域在 函数声明器。如果标识符指定了两个不同的 相同名称空间中的实体,作用域可能重叠。若有,详情为何? 一个实体的范围内部范围将严格在 其他实体的范围—外部范围。在内部范围内,, 标识符指定在内部范围中声明的实体;这个 外部范围中声明的实体在内部隐藏且不可见 内部范围

名为x的变量是一个内部作用域。因此,它在外部范围中隐藏名为x的实体。在main的范围内,在x的声明之后,它是一个变量名

有趣的是,在x中x={1,2};x的含义在声明中更改。开始时它表示类型名,但一旦声明器引入标识符,x就开始表示变量

关于你的编辑,这个论点有什么缺陷?请注意,如前段所述,范围可能重叠。类型别名的定义实际上在文件范围内。main的块范围是一个新的内部范围,它与外部范围重叠。这就是为什么它可以用来隐藏x之前的含义。您是否尝试在文件范围内执行此操作:

typedef struct x { /* ... */ } x;
int x = 1; // immediately at file scope

这将是不正确的。因为现在声明出现在完全相同的范围。

普通名称空间。请参阅@pmg:如果它是“普通”,那么两个程序都会显示编译错误请参阅int x和x x。。。否?@EML:尝试从x类型x定义另一个变量;xy;。呃,它不是和名字空间有关吗,6.2.3?具有不同名称空间的标记、结构成员和普通标识符。所以我认为这个答案不正确。@Lundin-typedef struct x{/**/}x;-这将x引入普通名称空间。OP询问的是x和变量x。或者在我看来是这样的。您的anser意味着声明xfoo引入了一个新的作用域,它允许隐藏第一个x。它是怎么做到的?@EML-不,它没有。标准段落指定范围是{}。但声明只是可见性开始的点。也就是说,变量在声明之前是不可见的。我阅读的问题是如何消除所有4X的歧义:标记、文件作用域typedef、成员和局部变量。这回答了文件范围和本地范围如何不冲突。但也许我误解了这个问题。
   x foo = { 1, 2 };
   int x = 3;        // 'x' in ordinary identifier name space
typedef struct x { /* ... */ } x;
int x = 1; // immediately at file scope