Suppose I have a.c
and b.c
, which both define types called struct foo
, with different definitions:
假设我有一个a.c和b.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);
}
In C, can these files both be linked together as part of a standards-conforming program?
在C中,这些文件是否可以作为符合标准的程序的一部分链接在一起?
(In C++, I believe this is forbidden by the One Definition Rule.)
(在C ++中,我认为One Definition Rule禁止这样做。)
3 个解决方案
#1
8
Struct tags are identifiers with no linkage (C11 6.2.2/6)
Struct标签是没有连接的标识符(C11 6.2.2 / 6)
The rules about multiple definitions of identifiers with no linkage are found in 6.7/3:
关于没有链接的标识符的多个定义的规则在6.7 / 3中找到:
If an identifier has no linkage, there shall be no more than one declaration of the identifier (in a declarator or type specifier) with the same scope and in the same name space, except that:
如果标识符没有链接,则标识符的声明(在声明符或类型说明符中)不得超过一个具有相同作用域和相同名称空间的声明,但以下情况除外:
- a typedef name may be redefined to denote the same type as it currently does, provided that type is not a variably modified type;
如果类型不是可变修改类型,则可以重新定义typedef名称以表示与其当前相同的类型;
- tags may be redeclared as specified in 6.7.2.3.
标签可以按照6.7.2.3中的规定重新声明。
In your program, the two declarations of foo
are in different scopes , so the condition "with the same scope" is not satisfied and therefore this rule is not violated.
在你的程序中,foo的两个声明属于不同的范围,因此不满足条件“具有相同的范围”,因此不违反此规则。
#2
1
The way to think about this is in terms of compilation units
. A .c
file, along with nested hierarchy of included .h
files, comprise a single compilation unit
. The pre-processor expands all the .h
files, and presents the entire compilation unit
to the compiler.
考虑这个问题的方法是编译单元。 .c文件以及包含的.h文件的嵌套层次结构包含单个编译单元。预处理器扩展所有.h文件,并将整个编译单元呈现给编译器。
A compilation unit
is a closed namespace for macros, type names, static identifiers, enums etc. These names cannot have duplicates within this namespace, and none of these names are visible outside this namespace. The implication is that a different compilation unit
is a separate, closed namespace - and may reuse the same identifiers, as long as there are no duplicates within that namespace.
编译单元是宏,类型名称,静态标识符,枚举等的封闭命名空间。这些名称在此命名空间中不能有重复项,并且这些名称在此命名空间外都不可见。这意味着不同的编译单元是一个单独的,封闭的命名空间 - 并且可以重用相同的标识符,只要该命名空间中没有重复项即可。
Therefore, you may use the same name for certain identifiers, as long as these are in separate compilation unit
namespaces.
因此,您可以对某些标识符使用相同的名称,只要它们位于单独的编译单元名称空间中即可。
Note that externally visible identifiers like non-static global variables, functions etc. need to be unique across the entire external namespace, which spans all the compilation units
linked together into a single executable.
请注意,外部可见标识符(如非静态全局变量,函数等)需要在整个外部命名空间中是唯一的,这跨越了链接在一起的所有编译单元到一个可执行文件中。
#3
0
In the C programming language, it doesn't matter what you call your types. Symbols are typed according to the structure of the type, not according to the type names. It is completely legal to use the same structure name for different structure types in different files. You can however not use different types to declare the same function.
在C编程语言中,您所谓的类型并不重要。符号是根据类型的结构键入的,而不是根据类型名称键入的。在不同文件中对不同结构类型使用相同的结构名称是完全合法的。但是,您可以不使用不同的类型来声明相同的功能。
#1
8
Struct tags are identifiers with no linkage (C11 6.2.2/6)
Struct标签是没有连接的标识符(C11 6.2.2 / 6)
The rules about multiple definitions of identifiers with no linkage are found in 6.7/3:
关于没有链接的标识符的多个定义的规则在6.7 / 3中找到:
If an identifier has no linkage, there shall be no more than one declaration of the identifier (in a declarator or type specifier) with the same scope and in the same name space, except that:
如果标识符没有链接,则标识符的声明(在声明符或类型说明符中)不得超过一个具有相同作用域和相同名称空间的声明,但以下情况除外:
- a typedef name may be redefined to denote the same type as it currently does, provided that type is not a variably modified type;
如果类型不是可变修改类型,则可以重新定义typedef名称以表示与其当前相同的类型;
- tags may be redeclared as specified in 6.7.2.3.
标签可以按照6.7.2.3中的规定重新声明。
In your program, the two declarations of foo
are in different scopes , so the condition "with the same scope" is not satisfied and therefore this rule is not violated.
在你的程序中,foo的两个声明属于不同的范围,因此不满足条件“具有相同的范围”,因此不违反此规则。
#2
1
The way to think about this is in terms of compilation units
. A .c
file, along with nested hierarchy of included .h
files, comprise a single compilation unit
. The pre-processor expands all the .h
files, and presents the entire compilation unit
to the compiler.
考虑这个问题的方法是编译单元。 .c文件以及包含的.h文件的嵌套层次结构包含单个编译单元。预处理器扩展所有.h文件,并将整个编译单元呈现给编译器。
A compilation unit
is a closed namespace for macros, type names, static identifiers, enums etc. These names cannot have duplicates within this namespace, and none of these names are visible outside this namespace. The implication is that a different compilation unit
is a separate, closed namespace - and may reuse the same identifiers, as long as there are no duplicates within that namespace.
编译单元是宏,类型名称,静态标识符,枚举等的封闭命名空间。这些名称在此命名空间中不能有重复项,并且这些名称在此命名空间外都不可见。这意味着不同的编译单元是一个单独的,封闭的命名空间 - 并且可以重用相同的标识符,只要该命名空间中没有重复项即可。
Therefore, you may use the same name for certain identifiers, as long as these are in separate compilation unit
namespaces.
因此,您可以对某些标识符使用相同的名称,只要它们位于单独的编译单元名称空间中即可。
Note that externally visible identifiers like non-static global variables, functions etc. need to be unique across the entire external namespace, which spans all the compilation units
linked together into a single executable.
请注意,外部可见标识符(如非静态全局变量,函数等)需要在整个外部命名空间中是唯一的,这跨越了链接在一起的所有编译单元到一个可执行文件中。
#3
0
In the C programming language, it doesn't matter what you call your types. Symbols are typed according to the structure of the type, not according to the type names. It is completely legal to use the same structure name for different structure types in different files. You can however not use different types to declare the same function.
在C编程语言中,您所谓的类型并不重要。符号是根据类型的结构键入的,而不是根据类型名称键入的。在不同文件中对不同结构类型使用相同的结构名称是完全合法的。但是,您可以不使用不同的类型来声明相同的功能。