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

时间:2019-05-13 09:07:08

标签: 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 ordinary identifier name space

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

这将使用gcc 4.4.7(和g ++ 4.4.7)打印出“ 1 2 3”,因此类型名称与标记,成员和普通标识符名称分开。

此代码还可以在gcc / g ++ 4.4.7上编译并运行,产生“ 1、2”:

#include <stdio.h>

typedef struct x {   // 'x' in tag namespace
   int x;            // 'x' in member namespace
   int y;
} x;

int main() {
   x x = { 1, 2 };

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

在这种情况下如何区分x标识符?

编辑 我希望澄清一下。从上面考虑这两行:

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

执行第二行时,标识符x在范围内,并且在逻辑上应位于“普通标识符”命名空间中。此时似乎没有 new 范围,因为第1行和第2行之间没有左括号。因此第二个x无法隐藏第一个{{1 }},第二个x错误。这个论点有什么缺陷,这对x的情况有何影响?我的假设是,缺陷在于类型名称在某种程度上具有不同的非显而易见的名称空间,因此是该问题的标题。

1 个答案:

答案 0 :(得分:4)

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

  

6.2.1标识符范围

     

2对于标识符指定的每个不同实体,   标识符仅在以下区域内可见(即可以使用)   程序文本称为其作用域。由指定的不同实体   同一标识符具有不同的范围或名称不同   空格。有四种范围:函数,文件,块和   功能原型。 (函数原型是对   函数来声明其参数的类型。)

     

4每个其他标识符的范围都取决于   其声明(在声明器或类型说明符中)。如果声明符   或声明标识符的类型说明符出现在任何   参数的块或列表,标识符具有文件范围,其中   在翻译单元的末尾终止。如果声明者或   声明标识符的类型说明符出现在块或   在函数定义的参数声明列表中,   标识符具有块作用域,该作用域终止于   关联的块。如果声明符或类型说明符声明   标识符出现在参数声明的列表中   函数原型(不是函数定义的一部分),标识符   具有函数原型作用域,该作用域终止于   函数声明符。如果标识符指定两个不同   同一名称空间中的实体,范围可能会重叠。如果是这样,   一个实体的范围(内部范围)将严格在   其他实体的范围(外部范围)。在内部范围内   标识符指定在内部范围内声明的实体;的   在外部作用域中声明的实体在其中隐藏(不可见)   内部范围。

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

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


关于您的编辑“此参数有何缺陷?” 请注意,范围可能重叠(如上一段所述)。类型别名的定义实际上是在文件范围内。 main的块作用域是与外部作用域重叠的新内部作用域。这就是为什么可以使用它来隐藏x的先前含义的原因。您是否尝试过在文件范围内执行此操作:

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

它会格式错误。因为现在声明确实出现在完全相同的范围内。

相关问题