Suppose I have a.c
and b.c
, which both define types called struct foo
, with different definitions:
#include <stdio.h>
struct foo {
int a;
};
int a_func(void) {
struct foo f;
f.a = 4;
printf("%d\n", f.a);
return f.a * 3;
}
#include <stdio.h>
struct foo { // same name, different members
char *p1;
char *p2;
};
void b_func(void) {
struct foo f;
f.p1 = "hello";
f.p2 = "world";
printf("%s %s\n", f.p1, f.p2);
}
In C, can these files both be linked together as part of a standards-conforming program?
(In C++, I believe this is forbidden by the One Definition Rule.)
Struct tags are identifiers with no linkage (C11 6.2.2/6)
The rules about multiple definitions of identifiers with no linkage are found in 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 may be redefined to denote the same type as it currently does, provided that type is not a variably modified type;
- tags may be redeclared as specified in 6.7.2.3.
In your program, the two declarations of foo
are in different scopes , so the condition "with the same scope" is not satisfied and therefore this rule is not violated.
The way to think about this is in terms of compilation units
. A .c
file, along with nested hierarchy of included .h
files, comprise a single compilation unit
. The pre-processor expands all the .h
files, and presents the entire compilation unit
to the compiler.
A compilation unit
is a closed namespace for macros, type names, static identifiers, enums etc. These names cannot have duplicates within this namespace, and none of these names are visible outside this namespace. The implication is that a different compilation unit
is a separate, closed namespace - and may reuse the same identifiers, as long as there are no duplicates within that namespace.
Therefore, you may use the same name for certain identifiers, as long as these are in separate compilation unit
namespaces.
Note that externally visible identifiers like non-static global variables, functions etc. need to be unique across the entire external namespace, which spans all the compilation units
linked together into a single executable.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With