同一个struct变量的多个声明好吗?

时间:2015-03-31 05:57:02

标签: c

以下是设置:

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的原因。令我惊讶的是,它仍然有效。

2 个答案:

答案 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_struct1constant object类型的my_struct。我希望你知道什么是常数变量。

my_struct my_struct2;

此处my_struct2my-struc t类型的对象。

总而言之,这些是2个不同的对象,并为它们分配了单独的内存,因此对于定义2个不同对象的同一个对象没有多个定义,这是完全正常的。