理解C命名空间

时间:2010-09-25 13:15:24

标签: c namespaces

引自here

  

在C中,有两种不同的类型名称空间:struct / union / enum标记名称的名称空间和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
$ 

我正在尝试了解C命名空间冲突。

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

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

4 个答案:

答案 0 :(得分:26)

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

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

另见C99 6.2.3。

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

  1. 是的,函数名和typedef名共享相同的名称空间。
  2. 没有冲突,因为编译器将使用范围规则(对于函数或对象名称)。 main中的标识符被称为 shadow 全局函数名称,如果您将警告级别设置得足够高,编译器会向您发出警告。

答案 1 :(得分:7)

但是你的例子的关键点不是名称空间,而是名称的范围。

name.c 中,long2都是“普通标识符”(共享相同的名称空间),并且它们都在同一范围内定义,因此存在冲突。 (C99§6.7/ 3)

如果 name2.c ,则局部变量four的范围比函数four更深,因此变量隐藏函数four(C99§6.2.1/ 4)。

答案 2 :(得分:6)

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

#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()

答案 3 :(得分:0)

快速回答您的两个问题。

Q1。在第一种情况下,为什么会有冲突?函数也属于typedef名称空间吗?

A1。是的,功能类型定义的类型的标识符共享相同的名称空间。因此存在冲突。

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

A2。在第二个示例中,即使两个名为 four 的标识符属于相同的标识符名称,即Ordinary namespace,也没有冲突。因为主要的变量标识符 four 功能范围中,而函数标识符 four 文件范围中>。因此,前者作为基本范围规则被后者隐藏了。如果将变量 four 移至如下所示的文件范围(全局),则会看到错误。

...

struct dummy four; // Error! there's a previous definition
                   // in this file scope(global).

int main() {
    // struct dummy four; // Commented out.
}

实际上,有四个不同的标识符名称空间:标签标签成员普通。您可以在https://en.cppreference.com/w/c/language/name_space

中找到有关它们的详细信息