理解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。

所以你的两个问题可以回答如下:

  1. 是的,函数名和typedef名共享相同的名称空间。
  2. 没有冲突,因为编译器将使用范围规则(用于函数或对象名称)。 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()