理解C命名空间
引自这里 ,
在C中,有两种不同的类型名称空间:struct / union / enum标记名称的名称空间和typedef名称的名称空间。
name.c
$ cat name.c #include typedef long long long2; int long2 () { return 4; } int main() { printf("hello, world!"); return 0; } $ gcc name.c -o name name.c:4: error: 'long2' redeclared as different kind of symbol name.c:3: error: previous declaration of 'long2' was here $
name2.c
$ cat name2.c #include int four() { return 4; } struct dummy { int member; }; int main() { struct dummy four; } $ gcc name2.c -o name2 $
我试图了解C名称空间冲突。
-
在第一种情况下,为什么会发生冲突? 函数是否也属于typedef命名空间?
-
在第二种情况下,为什么没有冲突呢? 函数和变量都命名为four。 为什么编译器允许这样做?
&four
应该如何解决?
C有四个不同的标识符名称空间:
- 标签名称(
goto
类型)。 - 标签(结构,联合和枚举的名称)。
- 结构和联合的成员(每个结构/联合具有单独的命名空间)。
- 所有其他标识符(函数名称,对象名称,类型(def)名称,枚举常量等)。
另见C99 6.2.3。
所以你的两个问题可以回答如下:
- 是的,函数名和typedef名共享相同的名称空间。
- 没有冲突,因为编译器将使用范围规则(用于函数或对象名称)。 main中的标识符被称为影响全局函数名称,如果您将警告级别设置得足够高,编译器会警告您。
但是关于你的例子的关键点不是名称空间,而是名称的范围。
在name.c中 , long2
都是“普通标识符”(共享相同的名称空间),并且它们都在同一范围内定义,因此存在冲突。 (C99§6.7/ 3)
如果name2.c ,局部变量four
的范围比函数four
深,所以变量隐藏了函数four
(C99§6.2.1/ 4)。
你的第二个例子没有显示“没有冲突”。 有冲突! 试试这个:
#include int four(void) { return 4; } struct dummy { int member; }; int main(void) { struct dummy four; four.member = four(); }
现在这个
#include int four(void) { return 4; } struct dummy { int member; }; int main(void) { int (*fx)(void) = four; /* "save" function */ struct dummy four; /* hide it */ four.member = fx(); /* use "hidden" fx */ }
在第二个例子中,变量four
隐藏了函数four()
。