Ben
Ben

Reputation: 2123

Multiple declaration of same struct variable ok?

Here's the setup:

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;
}

Which when compiled with gcc main.c foo.c prints 1 2. The question is, haven't I declared multiple variables with the same name (the two sets of structs)?

edit: Thanks for the reply all. I see I may have posed a slightly confusing question. Originally I thought const may have implied some sort of extern declaration (which makes no sense, I know), which is why I thought to create my_struct2. Much to my surprise, it still works.

Upvotes: 4

Views: 1359

Answers (2)

Vlad from Moscow
Vlad from Moscow

Reputation: 310950

According to the C Standard (6.9.2 External object definitions)

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.

Thus in your example these declarations of identifiers in header foo.h itself included in module foo.c

const my_struct my_struct1; 
my_struct my_struct2;

are not their external definitions because they do not have initializers.

These objects are externally defined only in module foo.c itself

const my_struct my_struct1 = { .a = 1 };
my_struct my_struct2 = { .a = 2 };

where they are explicitly initialized.

In module main.c these external declarations constitute tentative definitions and zero initialized.

According to the Appendix 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).

Thus the behaviour of the program is undefined unless your compiler supports the extension described in the Appendix J.

You should set specifier extern for these identifiers in header foo.h that the declarations in main.c would not constitute tentative definitions.

The one declaration rule is applied to identifiers that have no linkage. (6.7 Declarations)

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.

In your example all identifiers have external linkage. So they may be declared several times but defined only once.

Upvotes: 2

Gopi
Gopi

Reputation: 19864

const my_struct my_struct1; 

here my_struct1 is a constant object of type my_struct. I hope you know what is a constant variable.

my_struct my_struct2;

Here my_struct2 is a object of type my-struct.

So to sum it up these are 2 different objects and have separate memory allocated for them so there is no mutiple definitions for the same object you are defining 2 different objects which is totally fine.

Upvotes: 0

Related Questions