【问题标题】:understanding C namespaces理解 C 命名空间
【发布时间】:2011-04-17 04:12:43
【问题描述】:

引用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
$ 

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

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

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

【问题讨论】:

    标签: c namespaces


    【解决方案1】:

    C 有四种不同的标识符命名空间:

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

    另见 C99 6.2.3。

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

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

    【讨论】:

    • 结构/联合/枚举是否共享一个命名空间?即struct Tunion T 可以一起很好吗?
    【解决方案2】:

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

    name.c中,long2都是“普通标识符”(共享相同的命名空间),并且都定义在同一个作用域中,所以存在冲突。 (C99 §6.7/3)

    如果name2.c,局部变量four的作用域比函数four更深,所以变量隐藏函数four( C99 §6.2.1/4)。

    【讨论】:

      【解决方案3】:

      您的第二个示例未显示“无冲突”。有冲突!试试这个:

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

      【讨论】:

        【解决方案4】:

        快速回答您的两个问题。

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

        A1。是的,functionstypedef'ed 类型 的标识符共享相同的命名空间。所以有冲突。

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

        A2。即使名为 four 的两个标识符属于同一标识符命名空间,即Ordinary namespace,在您的第二个示例中也没有冲突。因为main中的变量标识符four函数作用域中,而函数标识符four文件作用域中>。所以后者被前者隐藏为基本范围规则。如果您将变量 four 移动到文件范围(全局),如下所示,您将看到一个错误。

        ...
        
        struct dummy four; // Error! there's a previous definition
                           // in this file scope(global).
        
        int main() {
            // struct dummy four; // Commented out.
        }
        

        实际上,有四种不同的标识符命名空间:LabelTagMemberOrdinary。您可以在https://en.cppreference.com/w/c/language/name_space找到有关它们的详细信息

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-08-26
          • 1970-01-01
          • 1970-01-01
          • 2012-02-25
          • 1970-01-01
          • 2021-12-16
          • 2015-01-01
          相关资源
          最近更新 更多