所以,据我所知,这在C中是合法的:
foo.c的
struct foo {
int a;
};
Run Code Online (Sandbox Code Playgroud)
bar.c
struct foo {
char a;
};
Run Code Online (Sandbox Code Playgroud)
但功能相同是非法的:
foo.c的
int foo() {
return 1;
}
Run Code Online (Sandbox Code Playgroud)
bar.c
int foo() {
return 0;
}
Run Code Online (Sandbox Code Playgroud)
并将导致链接错误(函数的多重定义foo).
这是为什么?结构名称和函数名称之间的区别是什么使C无法处理一个而不能处理另一个?这种行为也扩展到C++吗?
R S*_*ahu 24
这是为什么?
struct foo {
int a;
};
Run Code Online (Sandbox Code Playgroud)
定义用于创建对象的模板.它不会创建任何对象或功能.除非struct foo在代码中的某处使用,否则就编译器/链接器而言,这些代码行也可能不存在.
请注意,C和C++处理不兼容struct定义的方式有所不同.
struct foo您发布的代码中的不同定义在C程序中是可以的,只要您不混用它们的用法即可.
但是,它在C++中是不合法的.在C++中,它们具有外部链接,必须以相同的方式定义.有关详细信息,请参见3.2一个定义规则/ 5.
AnT*_*AnT 18
在这种情况下,区别概念称为联系.
在C struct中,union或enum标记没有链接.它们的范围实际上是本地的.
6.2.2标识符的链接
6以下标识符没有链接:声明为对象或函数以外的任何标识符; 声明为函数参数的标识符; 没有存储类说明符声明的对象的块作用域标识符extern.
它们不能在同一范围内重新声明(除了所谓的前向声明).但它们可以在不同的范围内自由重新声明,包括不同的翻译单元.在不同的范围内,他们可以声明完全独立的类型.这就是您的示例中的内容:在两个不同的翻译单元(即两个不同的文件范围)中,您声明了两种不同且不相关的struct foo类型.这是完全合法的.
同时,函数在C中具有链接.在您的示例中,这两个定义foo使用外部链接定义相同的函数.并且不允许在整个程序中提供任何外部链接功能的多个定义
6.9外部定义
5 [...]如果在表达式中使用了使用外部链接声明的标识符(除了作为结果为整数常量的运算符sizeof或_Alignof操作符的操作数的一部分),整个程序中的某个地方应该准确标识符的一个外部定义; 否则,不得超过一个.
在C++中,链接的概念得到了扩展:它为更广泛的实体(包括类型)分配特定的链接.在C++类类中有链接.在命名空间范围内声明的类具有外部链接.C++的一个定义规则明确指出,如果具有外部链接的类具有多个定义(跨不同的翻译单元),则应在所有这些翻译单元中等效地定义(http://eel.is/c++draft/basic .def.odr#12).因此,在C++中,您的struct定义将是非法的.
由于C++ ODR规则,您的函数定义在C++中仍然是非法的(但基本上与C中的原因相同).
Jon*_*ely 12
您的函数定义都声明了一个foo使用外部链接调用的实体,而C标准表示不能有多个具有外部链接的实体的定义.您定义的结构类型不是具有外部链接的实体,因此您可以拥有多个定义struct foo.
如果使用相同的名称声明具有外部链接的对象,那么这将是一个错误:
foo.c的
struct foo {
int a;
};
struct foo obj;
Run Code Online (Sandbox Code Playgroud)
bar.c
struct foo {
char a;
};
struct foo obj;
Run Code Online (Sandbox Code Playgroud)
现在你有两个被称为obj外部链接的对象,这是不允许的.
即使其中一个对象仅被声明而未定义,它仍然是错误的:
foo.c的
struct foo {
int a;
};
struct foo obj;
Run Code Online (Sandbox Code Playgroud)
bar.c
struct foo {
char a;
};
extern struct foo obj;
Run Code Online (Sandbox Code Playgroud)
这是未定义的,因为两个声明obj引用相同的对象,但它们没有兼容的类型(因为struct foo在每个文件中定义不同).
C++具有类似但更复杂的规则,以考虑inline函数和inline变量,模板和其他C++特性.在C++中,相关要求称为单一定义规则(或ODR).一个值得注意的区别是C++甚至不允许这两个不同的struct定义,即使它们从未用于声明具有外部链接的对象或在翻译单元之间"共享".