Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are different translation units allowed to define structures with the same name?

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.)

like image 843
user253751 Avatar asked Dec 23 '15 00:12

user253751


2 Answers

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.

like image 51
M.M Avatar answered Oct 17 '22 19:10

M.M


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.

like image 28
Ziffusion Avatar answered Oct 17 '22 20:10

Ziffusion