C:typedef struct name {…}; VS typedef struct {…}名称;

正如标题所说,我有这个代码:

typedef struct Book{ int id; char title[256]; char summary[2048]; int numberOfAuthors; struct Author *authors; }; typedef struct Author{ char firstName[56]; char lastName[56]; }; typedef struct Books{ struct Book *arr; int numberOfBooks; }; 

我从gcc得到这些错误:

 bookstore.c:8:2: error: unknown type name 'Author' bookstore.c:9:1: warning: useless storage class specifier in empty declaration [enabled by default] bookstore.c:15:1: warning: useless storage class specifier in empty declaration [enabled by default] bookstore.c:21:2: error: unknown type name 'Book' bookstore.c:23:1: warning: useless storage class specifier in empty declaration [enabled by default] 

如果我像这样更改typedef:

 typedef struct{ char firstName[56]; char lastName[56]; } Author; 

然后没有警告,也没有错误发生。 通过http://www.amazon.com/C-Programming-Language-2nd-Edition/dp/0131103628搜索了几个小时的谷歌搜索我无法弄清楚为什么第一个实现不起作用。

这里有几件事情。 首先,正如其他人所说,编译器对未知类型的抱怨可能是因为您需要在使用它们之前定义类型。 更重要的是要理解3件事的语法:(1)struct definition,(2)struct declaration,和(3)typedef。

定义结构时,结构可以命名或未命名(如果未命名,则必须立即使用(将解释这意味着下面的内容))。

 struct Name { ... }; 

这定义了一个名为“struct Name”的类型,然后可以用它来声明一个struct变量:

 struct Name myNameStruct; 

这声明了一个名为myNameStruct的变量,它是struct Name类型的struct Name

您还可以定义结构,并同时声明结构变量:

 struct Name { ... } myNameStruct; 

和以前一样,这声明了一个名为myNameStruct的变量,它是struct Name类型的struct Name但是它在定义 struct Name 类型的同时执行它
该类型可以再次用于声明另一个变量:

 struct Name myOtherNameStruct; 

现在,typedef只是一种为具有特定名称的类型添加别名的方法:

 typedef OldTypeName NewTypeName; 

给定上面的typedef,无论NewTypeName使用NewTypeName它都与使用OldTypeName相同。 在C编程语言中,这对于结构体特别有用,因为它使您能够在声明该类型的变量时将单词“struct”放下,并将结构的名称简单地视为一个类型(就像我们在C ++)。 下面是一个示例,首先定义struct,然后键入struct struct:

 struct Name { ... }; typedef struct Name Name_t; 

在上面的OldTypeName中是struct Name ,NewTypeName是Name_t 。 所以现在,声明一个struct Name类型的变量,而不是写:

 struct Name myNameStruct; 

我可以简单地写一下:

 Name_t myNameStruct; 

另请注意,typedef可以与结构定义结合使用,这就是您在代码中所做的事情:

 typedef struct { ... } Name_t; 

这也可以在命名结构时完成,但这是多余的:

 typedef struct Name { ... } Name_t; 

注意:在上面的语法中,由于您已经开始使用“typedef”,因此整个语句是一个typedef语句,其中OldTypeName恰好是一个结构定义。 因此,编译器将右大括号后面的名称解释为NewTypeName …它不是变量名称(因为它将在没有typedef的语法中,在这种情况下,您将定义结构并声明结构变量同时)。

此外,如果你声明了typedef,但是在结尾处没有关闭Name_t,那么你已经有效地创建了一个INCOMPLETE typedef语句 ,因为编译器将“ struct Name { ... } ”中的所有内容视为OldTypeName,并且你没有提供typedef的NewTypeName。 这就是为什么编译器对代码不满意的原因(尽管编译器的消息相当神秘,因为它不太确定你做错了什么)。

现在,正如我上面提到的,如果在定义结构类型时没有命名结构类型,那么必须立即使用它来声明变量:

 struct { ... } myNameStruct; // declares myNameStruct as a variable with this struct // definition, but the definition cannot be re-used. 

或者您可以在typedef中使用未命名的结构类型:

 typedef struct { ... } Name_t; 

最后的语法是你写的时候实际做的:

 typedef struct{ char firstName[56]; char lastName[56]; } Author; 

编译器很高兴。 HTH。

关于_t后缀的评论/问题:

_t后缀是一种约定,用于向读取代码的人员指示带有_t的符号名称是类型名称(而不是变量名称)。 编译器不解析也不知道_t。

C89,特别是C99,标准库定义了许多类型,并选择使用_t作为这些类型的名称。 例如,C89标准定义了wchar_t,off_t,ptrdiff_t。 C99标准定义了许多额外的类型,例如uintptr_t,intmax_t,int8_t,uint_least16_t,uint_fast32_t等。但_t不是保留的,也没有特别解析,也没有被编译器注意到,它只是一个很好的遵循的约定当您在C中定义新类型(通过typedef)时。在C ++中,许多人使用约定来启动大写的类型名称,例如,MyNewType(而不是C约定my_new_type_t)。 HTH

语法是typedef如下:

 typedef old_type new_type 

在第一次尝试中,您定义了struct Book类型而不是 Book 。 换句话说,您的数据类型称为struct Book而不是Book

在第二种forms中,您使用了typedef的正确语法,因此编译器会识别名为Book的类型。

您只需在定义Book之前定义Author。

您在Book中使用Author,因此需要先定义它。

我想会帮助你理解。 http://www.tutorialspoint.com/cprogramming/c_typedef.htm

 bookstore.c:8:2: error: unknown type name 'Author' bookstore.c:21:2: error: unknown type name 'Book' 

这些是因为您必须在使用它们之前定义它们。 将结构“作者”和“书籍”移动到结构“书籍”上方。 这将解决它。

你得到的警告也解释了为什么存在问题,编译器将“typedef struct Author”标识为不必要,因为你没有正确地键入结构,因此编译器没有任何“读取”的用处。

既然你已经知道答案应该采用这种forms

 typedef struct { ... ... ... } struct-name; 

坚持下去。