2010-09-25 108 views
15

here报价,了解ç命名空间

在C,有类型的两个不同的命名空间:结构/联合/枚举标记名称的命名空间和typedef名称的命名空间。

name.c

$ cat name.c 
#include<stdio.h> 

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<stdio.h> 

int four() { 
    return 4; 
} 

struct dummy { 
    int member; 
}; 

int main() { 

    struct dummy four; 
} 

$ gcc name2.c -o name2 
$ 

我想了解Ç命名空间冲突。

  • 在第一种情况下,为什么会出现冲突?函数是否也属于typedef命名空间?

  • 在第二种情况下,为什么没有冲突呢?函数和变量都被命名为四。为什么编译器允许这样做? &four应该如何解决?

回答

20

C有四个不同的名字空间标识符:

  • 标签的名称(goto型)。
  • 标签(结构,工会和枚举的名称)。
  • 结构和联合的成员(每个结构/联合都有单独的名称空间)。
  • 所有其他标识符(函数名称,对象名称,类型(def)名称,枚举常量等)。

另请参阅C99 6.2.3。

  1. 是,函数名和typedef名称共享相同的命名空间:

    所以你的两个问题可以作为回答。

  2. 没有冲突,因为编译器将使用作用域规则(用于函数或对象名称)。主标识符称为shadow全局函数名称,如果将警告级别设置得足够高,则编译器会警告您。
+0

结构/联合/枚举是否共享一个名称空间?也就是说'struct T'和'union T'能够很好的结合在一起吗? – iBug 2017-11-17 10:00:03

5

你的第二个例子不显示“没有冲突”。有冲突!试试这个:

#include <stdio.h> 
int four(void) { return 4; } 
struct dummy { int member; }; 
int main(void) { 
    struct dummy four; 
    four.member = four(); 
} 

现在这个

#include <stdio.h> 
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()

6

但是,您的示例中的关键点不是关于名称空间,而是名称的范围。

name.c,既long2是“普通的标识符”(共享相同的命名空间),且二者在同一范围内定义,因此有冲突。 (C99 § 6.7/3)

如果name2.c,局部变量four在比功能four深的范围,所以可变兽皮功能four(C99 § 6.2.1/4) 。