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
的情况有何影响?我的假设是,缺陷在于类型名称在某种程度上具有不同的非显而易见的名称空间,因此是该问题的标题。
答案 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
它会格式错误。因为现在声明确实出现在完全相同的范围内。