-1
#define MyStruct(T) struct {T data;}

void foo(MyStruct(int) s);

void foo(MyStruct(int) s) {
    return;
}

int main(void) {
    //...
    return 0;
}

这会导致错误:

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);
     ^

如果我创建一个 typedef,例如typedef MyStruct(int) MyIntStruct;并使用它,则没有错误。

所以我的问题是,为什么会出现冲突类型错误?是否所有匿名结构都是唯一的,例如编译器无法确定它们是否是完全相同的类型?

4

1 回答 1

1

首先,这些是没有标签的结构声明,而不是匿名结构。匿名结构是没有名称的结构,而不是没有标签的结构声明。例如:

struct outer
{
    struct inner { int x; int y; };
    int z;
} s;

在这段代码中,struct里面的成员s没有成员名,所以是匿名的。我们没有可以引用该结构的名称,我们将其成员称为s.xand s.y,而不是s.something.xand s.something.y

没有标签的结构的每个声明都声明不同类型的原因是 C 2018 6.7.2.3 5 说:

… 不包含标记的结构、联合或枚举类型的每个声明都声明了不同的类型。

造成这种情况的原因有时是我们将具有相同内容的结构用于不同的目的。例如,我们可能有一个具有两个double值的结构,用于复数(实部和虚部)和一个具有两个double值的结构,用于平面中的点(xy坐标):

typedef struct { double d[2]; } ComplexNumber;
typedef struct { double d[2]; } Point;

让编译器将这些视为不同的类型意味着它可以向我们发出有关错误的警告,例如将 aPoint作为参数传递给Complex预期的 a 。

正如您所指出的, atypedef为类型创建了一个新名称。然后使用typedef名称指的是现有类型。它不会“重复”声明struct并创建新类型。

于 2021-07-07T10:25:14.740 回答