13

假设我有a.cb.c,它们都定义了名为struct foo的类型,但定义不同:

#include <stdio.h>

struct foo {
    int a;
};

int a_func(void) {
    struct foo f;
    f.a = 4;
    printf("%d\n", f.a);
    return f.a * 3;
}

 

#include <stdio.h>

struct foo { // same name, different members
    char *p1;
    char *p2;
};

void b_func(void) {
    struct foo f;
    f.p1 = "hello";
    f.p2 = "world";
    printf("%s %s\n", f.p1, f.p2);
}

在 C 中,这些文件可以作为符合标准的程序的一部分链接在一起吗?

(在 C++ 中,我相信这是单一定义规则所禁止的。)

4

3 回答 3

10

结构标签是没有链接的标识符(C11 6.2.2/6)

在 6.7/3 中可以找到关于没有链接的标识符的多个定义的规则:

如果标识符没有链接,则标识符的声明(在声明符或类型说明符中)不得超过一个具有相同范围和相同名称空间的声明,但以下情况除外:

  • 可以重新定义 typedef 名称以表示与当前相同的类型,前提是该类型不是可变修改的类型;
  • 标签可以按照 6.7.2.3 中的规定重新声明。

在您的程序中, 的两个声明foo在不同的范围内,因此不满足“具有相同范围”的条件,因此不违反此规则。

于 2015-12-23T00:59:06.153 回答
2

考虑这一点的方法是根据compilation units. 一个.c文件,连同包含.h文件的嵌套层次结构,组成一个compilation unit. 预处理器扩展所有.h文件,并将整个文件呈现compilation unit给编译器。

Acompilation unit是宏、类型名称、静态标识符、枚举等的封闭名称空间。这些名称在此名称空间内不能有重复项,并且这些名称在此名称空间外均不可见。这意味着不同compilation unit的是一个单独的、封闭的命名空间——并且可以重用相同的标识符,只要命名空间内没有重复。

因此,您可以为某些标识符使用相同的名称,只要它们位于不同的compilation unit命名空间中。

请注意,外部可见的标识符(如非静态全局变量、函数等)在整个外部命名空间中必须是唯一的,该命名空间将所有链接在一起的内容跨越compilation units到一个可执行文件中。

于 2015-12-23T01:49:37.510 回答
0

在 C 编程语言中,你如何称呼你的类型并不重要。符号是根据类型的结构而不是根据类型名称来键入的。在不同的文件中为不同的结构类型使用相同的结构名称是完全合法的。但是,您不能使用不同的类型来声明相同的函数。

于 2015-12-23T00:46:23.803 回答