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

这是设置:

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可能隐含了某种外部声明(我知道这没有意义),这就是我想创建my_struct2的原因.令我惊讶的是,它仍然有效.

最佳答案 根据C标准(6.9.2外部对象定义)

1 If the declaration of an identifier for an object has file scope and
an initializer, the declaration is an external definition for the
identifier.

2 A declaration of an identifier for an object that has file scope
without an initializer, and without a storage-class specifier or with
the storage-class specifier static, constitutes a tentative
definition. If a translation unit contains one or more tentative
definitions for an identifier, and the translation unit contains no
external definition for that identifier, then the behavior is exactly
as if the translation unit contains a file scope declaration of that
identifier, with the composite type as of the end of the translation
unit, with an initializer equal to 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 Multiple external definitions 1 There may be more than one
external definition for the identifier of an object, with or without
the explicit use of the keyword extern; if the definitions disagree,
or more than one is initialized, the behavior is undefined (6.9.2).

因此,除非您的编译器支持附录J中描述的扩展,否则程序的行为是未定义的.

你应该在header foo.h中为这些标识符设置说明符extern,main.c中的声明不构成暂定定义.

一个声明规则适用于没有链接的标识符. (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 can be redefined to denote the same type as it currently does and
tags may be redeclared as specified in 6.7.2.3.

在您的示例中,所有标识符都有外部链接所以它们可能会被声明几次,但只定义一次.

点赞