C++ 范围中的结构与函数定义
据我所知,这在C中是合法的: foo.cC++ 范围中的结构与函数定义,c++,c,linkage,C++,C,Linkage,据我所知,这在C中是合法的: foo.c struct foo { int a; }; struct foo { char a; }; int foo() { return 1; } int foo() { return 0; } bar.c struct foo { int a; }; struct foo { char a; }; int foo() { return 1; } int foo() { return 0
struct foo {
int a;
};
struct foo {
char a;
};
int foo() {
return 1;
}
int foo() {
return 0;
}
bar.c
struct foo {
int a;
};
struct foo {
char a;
};
int foo() {
return 1;
}
int foo() {
return 0;
}
但同样的事情对于函数也是非法的:
foo.c
struct foo {
int a;
};
struct foo {
char a;
};
int foo() {
return 1;
}
int foo() {
return 0;
}
bar.c
struct foo {
int a;
};
struct foo {
char a;
};
int foo() {
return 1;
}
int foo() {
return 0;
}
并将导致链接错误(函数的多个定义foo
)
为什么呢?结构名和函数名之间有什么区别使得C不能处理其中一个而不能处理另一个?
这种行为是否也扩展到C++?< /p>
为什么呢
定义用于创建对象的模板。它不创建任何对象或函数。除非struct foo
在代码中的某个地方使用,否则就编译器/链接器而言,这些代码行也可能不存在
<>请注意,C和C++如何处理不兼容的<代码>结构> <代码>定义。
在您发布的代码中,struct foo
的不同定义在C程序中是可以的,只要您不混合使用它们
<>但是,C++中不合法。在C++中,它们具有外部链接,必须定义相同。有关更多详细信息,请参阅。与其说名称不同,不如说存在差异;结构定义不存储在任何位置,其名称仅在编译期间存在。
(程序员有责任确保在使用同名结构时不存在冲突。否则,我们亲爱的老朋友Undefined Behavior会打电话来。) 另一方面,函数需要存储在某个地方,如果它有外部链接,则链接器需要它的名称
如果将函数设置为静态,使其在各自的编译单元外“不可见”,则链接错误将消失。函数定义都声明了一个名为
foo
的实体,该实体具有外部链接,C标准规定,对于具有外部链接的实体,不能有一个以上的定义。您定义的结构类型不是具有外部链接的实体,因此可以有多个struct foo
定义
如果使用相同的名称声明具有外部链接的对象,则这将是一个错误:
富科
酒吧c
现在有两个名为obj
的对象,它们都具有外部链接,这是不允许的
即使其中一个对象只是声明的,而不是定义的,它仍然是错误的:
富科
酒吧c
这是未定义的,因为obj
的两个声明引用同一个对象,但它们没有兼容的类型(因为struct foo
在每个文件中的定义不同)
C++有类似但更复杂的规则,用于解释<代码>内联< /COD>函数和<代码>内联< /COD>变量、模板和其他C++特性。在C++中,相关的要求被称为一个定义规则(ODR)。一个显著的区别是,C++甚至不允许两个不同的代码<结构> /COD>定义,即使它们从不用于声明具有外部链接的对象,也不被用于“共享”。翻译单元之间。
struct foo的两个声明互不兼容,因为成员的类型不同。在每个翻译单元中都使用这两种语言是可以的,只要您不做任何事情来混淆这两种语言 例如,如果您这样做: foo.c:struct foo {
char a;
};
void bar_func(struct foo *f);
void foo_func()
{
struct foo f;
bar_func(&f);
}
B.c:
struct foo {
int a;
};
void bar_func(struct foo *f)
{
f.a = 1000;
}
您将进行调用,因为bar_func
期望的struct foo
与foo_func
提供的struct foo
不兼容
结构的兼容性详见本手册第6.2.7节:
1如果两种类型相同,则它们具有兼容类型。确定两种类型是否兼容的其他规则包括
6.7.2中描述了类型说明符,6.7.3中描述了类型限定符,
在6.7.6中,对于声明者。此外,两个结构、联合或
在单独的转换单元中声明的枚举类型是兼容的
其标签和成员是否满足以下要求:如果
使用标签声明的,另一个应使用相同的标签声明。
如果两者都在各自翻译范围内的任何地方完成
单位,则以下附加要求适用:应
成员之间的一对一通信,以便
使用兼容类型声明一对对应的成员;如果
使用对齐说明符声明对中的一个成员,即
另一个是使用等效的对齐说明符声明的;如果有
对中的一个成员用名称声明,另一个成员用名称声明
同名。对于两个结构,应使用相应的构件
以相同的顺序声明。对于两个结构或联合体,
相应的位字段应具有相同的宽度。两个人
枚举时,相应的成员应具有相同的值
2所有引用相同对象或函数的声明应具有兼容类型;否则,行为是未定义的
总之,struct foo
的两个实例必须具有相同名称和类型且顺序相同的成员才能兼容
需要这样的规则,以便可以在头文件中定义一次
struct
,并且该头随后包含在多个源文件中。这将导致在多个源文件中定义结构,但每个实例都是兼容的。要对链接器隐藏函数定义,请使用关键字static
富科
酒吧c
在这种情况下,区别概念称为链接
在C结构中,union或enum标记没有链接。它们实际上是其范围的局部
6.2.2标识符的链接
6以下标识符没有链接:已声明的标识符