以下是设置:
foo.h中:
typedef struct my_struct {
int a;
} my_struct;
const my_struct my_struct1;
my_struct my_struct2;
foo.c的:
#include "foo.h"
const my_struct my_struct1 = { .a = 1 };
my_struct my_struct2 = { .a = 2 };
main.c中:
#include "foo.h"
#include <stdio.h>
int main() {
printf("%d %d\n", my_struct1.a, my_struct2.a);
return 0;
}
使用gcc main.c foo.c
编译时打印1 2
。问题是,我没有声明多个具有相同名称的变量(两组结构)?
编辑:感谢您的回复。我看到我可能提出了一个有点令人困惑的问题。最初我认为const
可能隐含了某种extern
声明(我知道这没有意义),这就是我想创建my_struct2
的原因。令我惊讶的是,它仍然有效。
答案 0 :(得分:2)
根据C标准(6.9.2外部对象定义)
1如果对象的标识符声明具有文件范围和 一个初始化器,声明是一个外部定义 标识符
2具有文件范围的对象的标识符声明 没有初始化程序,没有存储类说明符或没有 存储类说明符静态,构成一个暂定的 定义。如果翻译单元包含一个或多个暂定单元 标识符的定义,翻译单元包含否 该标识符的外部定义,然后行为是完全正确的 好像翻译单元包含一个文件范围声明 标识符,在翻译结束时使用复合类型 单位,初始化程序等于0。
因此,在您的示例中,头文件foo.h中的标识符声明包含在模块foo.c中
const my_struct my_struct1;
my_struct my_struct2;
不是他们的外部定义,因为他们没有初始化器。
这些对象仅在模块foo.c
本身
const my_struct my_struct1 = { .a = 1 };
my_struct my_struct2 = { .a = 2 };
它们被明确初始化。
在模块main.c中,这些外部声明构成暂定定义并初始化为零。
根据附录J
J.5.11多个外部定义1可能有多个外部定义 对象标识符的外部定义,有或没有 关键字extern的显式使用;如果定义不一致, 或者初始化多个行为,行为未定义(6.9.2)。
因此,除非您的编译器支持附录J中描述的扩展,否则程序的行为是未定义的。
您应该在标头foo.h中为这些标识符设置说明符extern
,即main.c中的声明不构成暂定定义。
一个声明规则适用于没有链接的标识符。 (6.7声明)
3 如果标识符没有链接,则不得超过一个 标识符声明(在声明符或类型说明符中) 具有相同的范围和相同的名称空间,除了typedef name可以重新定义,以表示与当前相同的类型 标签可以按照6.7.2.3中的规定重新声明。
在您的示例中,所有标识符都具有外部链接。所以它们可能会被声明几次,但只定义一次。
答案 1 :(得分:0)
const my_struct my_struct1;
此处my_struct1
是constant object
类型的my_struct
。我希望你知道什么是常数变量。
my_struct my_struct2;
此处my_struct2
是my-struc
t类型的对象。
总而言之,这些是2个不同的对象,并为它们分配了单独的内存,因此对于定义2个不同对象的同一个对象没有多个定义,这是完全正常的。