#define MyStruct(T) struct {T data;}
void foo(MyStruct(int) s);
void foo(MyStruct(int) s) {
return;
}
int main(void) {
//...
return 0;
}
This results in an error:
main.c:7:6: error: conflicting types for 'foo'
void foo(MyStruct(int) s) {
^
main.c:5:6: note: previous declaration is here
void foo(MyStruct(int) s);
^
There's no error if I create a typedef, such as typedef MyStruct(int) MyIntStruct;
and use that.
So my question is, why do I get the conflicting type error? Are all anonymous structs unique, like the compiler won't determine whether they're the exact same type?
First, these are structure declarations without tags, not anonymous structures. An anonymous structure is a structure without a name, not a structure declaration without a tag. For example:
struct outer
{
struct inner { int x; int y; };
int z;
} s;
In this code, the struct
member inside s
does not have a member name, so it is anonymous. We have no name that can refer to that structure, and we refer to its members as s.x
and s.y
, rather than s.something.x
and s.something.y
.
The reason each declaration of a structure without a tag declares a distinct type is C 2018 6.7.2.3 5 says:
… Each declaration of a structure, union, or enumerated type which does not include a tag declares a distinct type.
A reason for this is sometimes we use structures that have identical contents for different purposes. For example, we might have a structure with two double
values that we use for complex numbers (real and imaginary parts) and a structure with two double
values that we use for points in a plane (x and y coordinates):
typedef struct { double d[2]; } ComplexNumber;
typedef struct { double d[2]; } Point;
Having the compiler treat these as different types means it can give us warnings about mistakes like passing a Point
as an argument where a Complex
is expected.
As you have noted, a typedef
creates a new name for a type. Then using the typedef
name refers to that existing type. It does not “repeat” the declaration of the struct
and create a new type.