我参考了下面的教程,后来发现使用typedef声明struct是错误的方法。
typedef struct
{
char name[namesize];
char address[addresssize];
int YearOfBirth;
int MonthOfBirth;
int DayOfBirth;
} PersonalData;
然后声明:
PersonalData x;
但是,我认为正确的方法是
typedef struct personaldataStruct
{
char name[namesize];
char address[addresssize];
int YearOfBirth;
int MonthOfBirth;
int DayOfBirth;
} PersonalData;
然后声明:
PersonalData x;
作者是否误导了我?或两种方式都是正确的?请确认。 这是教程http://www.iu.hio.no/~mark/CTutorial/CTutorial.html
答案 0 :(得分:3)
任何一种方法都没有正式的“不正确”。
前者为该结构类型声明了无标记结构类型和typedef名称PersonalData
。后者为该结构类型声明了结构类型struct personaldataStruct
和同义typedef名称PersonalData
。声明的personaldataStruct
部分通常称为“struct tag”。
只要您使用PersonalData
typedef名称来引用该结构类型,就像在
PersonalData x;
你不会看到两个声明之间有任何区别。在这两种情况下,x
都将被声明为相同。
后一种方法为您提供了一种引用相同结构类型的替代方法 - struct personaldataStruct
- 如果由于某种原因您希望这样做。例如。使用后一种声明时,您也可以将x
声明为
struct personaldataStruct x;
完全等同于PersonalData x;
声明。
就个人而言,我更喜欢使用带有struct标签的方法,因为它为我提供了引用类型的替代方法,这在某些情况下可能会派上用场(例如,当结构类型必须引用自身时)。但在大多数非自我指涉的情况下,使用前一种方法完全没问题。
答案 1 :(得分:0)
两者都是正确的。第一种形式(没有标签)的唯一真正问题是,因为typedef名称在定义结束之前不可见,所以无法从自己的定义中引用结构。这是一个普遍的要求;例如,链表,树或其他类似图形的数据结构中的节点通常需要指向同一类型的其他对象。
由于struct标签和typedef名称位于不同的名称空间(不要与C ++名称空间混淆),因此不需要它们是不同的。对两者使用相同的标识符是完全可以接受的:
typedef struct PersonalData {
/* ... */
struct PersonalData *next;
} PersonalData;
或者,只要你要同时拥有一个标签和一个typedef,你就可以转发声明typedef:
typedef struct PersonalData PersonalData;
/* At this point, "struct PersonalData is an incomplete type. */
struct PersonalData {
/* ... */
PersonalData *next;
};
/* And now "struct PersonalData" is a complete type. */
(但是拼写错误会让你留下typedef
仍然指的是一个从未完成的不完整类型,这可能会触发难以追踪的错误。复制粘贴是你的朋友。)
还有另一种选择。您定义的类型已经有一个名称:struct PersonalData
。 typedef
所做的只是给同一个类型一个不同的名字。很高兴能够使用单个标识符作为类型名称,但实际上没有必要。我自己的偏好是完全省略typedef
,只需将类型称为struct PersonalData
:
struct PersonalData {
/* ... */
struct PersonalData *next;
};
struct PersonalData *head;
struct PersonalData fred;
除非PersonalData
意味着是一个opaque类型(意味着使用它的代码不需要知道它是一个结构),所以显式有一些优势。
很多人在这一点上强烈反对我,并且非常喜欢将typedef用于结构,你可能会在评论中看到。使用像这样的typedef没有错;这没有必要。您应该准备好阅读其他人使用任何一种风格编写的代码。