2013-10-10 141 views
0

我参考了下面的教程,后来认识到这是使用typedef声明结构的错误方法。Typedef结构错误声明?

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

+1

恕我直言,两种方式都是正确的。 –

+0

我也在想这个.. – noufal

回答

2

这两种方法都没有正式的“不正确”。

前者为该结构类型声明一个无标签结构类型和一个typedef名称PersonalData。后者为该结构类型声明一个结构类型struct personaldataStruct和同义类型定义名称PersonalData。声明的personaldataStruct部分通常被称为“结构标签”。

只要你使用PersonalData的typedef名指的是结构类型,如

PersonalData x; 

你不会看到这两个声明之间的任何差别。在这两种情况下,x将被相同地声明。

后一种方法为您提供了另一种引用相同结构类型的方法 - struct personaldataStruct - 如果由于某种原因您希望这样做。例如。使用后声明时,你也可以声明x作为

struct personaldataStruct x; 

这是完全等同于PersonalData x;声明。我个人更喜欢使用带有结构标签的方法,因为它为我提供了另一种引用类型的方法,这在某些情况下可能会派上用场(例如,当结构类型必须引用自身时) 。但是在大多数非自我指称的情况下,对于前一种方法来说,情况会很好。

+0

完美,你不仅回答了我的问题,而且还举了一个例子“(例如,当结构类型必须引用自己)。”这就是我问这个的原因。我以前的方法遇到链接列表节点声明问题。 –

0

两者都是正确的。第一种形式(没有标签)唯一的问题是,因为typedef名称在定义结束之前不可见,所以没有办法从它自己的定义中引用该结构。这是一个共同的要求;例如,链接列表,树或其他类似图形的数据结构中的节点通常需要指向相同类型的其他对象。

由于结构标记和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意味着是一个不透明的类型(也就是说,使用它并不需要知道它的代码一个结构体),在显式中有一些优点。

在这一点上,很多人都非常反对我,并且真的很喜欢在结构中使用typedef,因为您可能会在评论中看到。使用像这样的typedefs没有任何问题;这是没有必要的。你应该准备阅读别人用任何一种风格写的代码。

+0

谢谢Keith!我已经选择了答案,但是你的答案和其他答案一样好。 –

+0

@DavidPrun:谢谢。 http://meta.stackexchange.com/a/5235/167210 –