4

I read that in C11 typedef redefinition is allowed, as long as the definitions are the same. However the following code

typedef struct {
    int x;
} a_t;

typedef struct {
    int x;
} a_t;

int main(int argc, char* argv[]) {
    a_t a;
    return a.x + argc;
}

when compiled with C11 flag gives me a redefinition error:

% clang -std=c11 -o x x.c
x.c:7:3: error: typedef redefinition with different types ('struct a_t' vs 'struct a_t')
} a_t;
  ^
x.c:3:3: note: previous definition is here
} a_t;
  ^
1 error generated.

Interestingly, if the typedef is just a primitive type (i.e. 'typedef int a_t;') then redefinition does not throw error, even without the '-std=c11' flag.

Why can't types with structs be redefined?

This is an issue where definitions coming from 3rd party headers.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
lipi
  • 53
  • 4
  • 2
    The two `structs` are not the same type even though they have the same fields. What you can do is to define a (single) named struct and then define multiple same typedefs to that named struct. – kaylum Jun 10 '21 at 22:24
  • 1
    @kaylum: That should be an answer. – R.. GitHub STOP HELPING ICE Jun 10 '21 at 22:26
  • 1
    I suspect some people are already writing answers, but if you're looking for the Standard reference, it's 6.7.2.3 (5): "Each declaration of a structure, union, or enumerated type which does not include a tag declares a distinct type." This is so even if they have the same members in the same order; there's no exception for that case. – Nate Eldredge Jun 10 '21 at 22:30

2 Answers2

5

The two structs are not the same type even though they have the same fields. One can see this more clearly with named structs:

struct first {
    int x;
};

struct second {
    int x;
};

Clearly these are two different structs even though they have the same fields.

So in your case a single named struct can be defined and then typedef redefinitions will work.

$ cat test.c
struct A {
    int x;
};

typedef struct A a_t;
typedef struct A a_t;

int main(void)
{

}

$ clang -std=c99 test.c
test.c:6:18: warning: redefinition of typedef 'a_t' is a C11 feature
      [-Wtypedef-redefinition]
typedef struct A a_t;
                 ^
test.c:5:18: note: previous definition is here
typedef struct A a_t;
                 ^
1 warning generated.

$ clang -std=c11 test.c
$ 
kaylum
  • 13,833
  • 2
  • 22
  • 31
  • Thanks @kaylum it does make sense. Unfortunately the 3rd party headers both use anonymous structs in their typedefs, so I will have to find some other solutions. – lipi Jun 14 '21 at 02:13
0

In these declarations

typedef struct {
    int x;
} a_t;

typedef struct {
    int x;
} a_t;

there are used two unnamed structures that are considered as two different types.

So the alias name a_t is defined for two different types.

If to imagine that the typedefs use the same type then in any case the unnamed structure is redefined that is it is defined twice.

That is if you will write for example

struct A
{
    int x;
};

struct A
{
    int x;
};

then the compiler also will issue a similar error message that in this case the structure A is redefined.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335