Understanding typedef with struct
我很难理解这个代码示例:
1 2 3 4 5 6 7 | typedef struct node { int data; struct node * next; } node; typedef node * nodepointer; |
所以,我们正在使用typedef构建结构节点…我假设我们这样做是为了在不需要"struct"关键字的情况下初始化结构。
我想问一下为什么在结构定义中我们使用了两次"node"这个名称(从开始到结束)。
其次,
首先,让我们在这里澄清一下:
1 | typedef <type specifier> new_type_name; |
所以这里发生的事情对未经训练的人来说肯定是骗人的。
我一会儿会更多地了解
然后,周围的
这是因为在C(不像C++)中使用结构的标签名需要用EDCOX1(2)来预定义类型。
1 2 3 4 5 6 | struct Foo { // ... }; Foo bar; // ERROR struct Foo bar; // OK |
使用typedef,我们将结构命名为typename,称为
1 2 3 4 5 6 7 8 9 | typedef struct Foo { // ... } FooType; Foo bar; // ERROR struct Foo bar; // OK FooType bar; // OK struct FooType bar; // ERROR |
请记住,您可以定义不带标记的结构,因此可以定义
1 2 3 4 5 | typedef struct { // ... } FooType; FooType bar; // OK |
不过,我将在示例中解释为什么您不能这样做。
示例中的属性
在定义不完整的类型之前,不能使用它们,除非您指向它们。
1 2 3 4 5 6 7 8 9 10 | struct Foo; struct Foo bar; // ERROR: Foo is not defined. struct Foo *bar; // OK - it's just a pointer. We know the size of a pointer. struct Foo { // ... }; struct Foo bar; // OK - it's defined now. |
因此,根据类型
你也可以推断,直接使用
1 2 3 4 | struct node { struct node next; // ERROR - `struct node` becomes infinitely big struct node *next; // OK - a pointer is usually 4/8 bytes (we at least know its size at this point) }; |
回答最后三个问题:
What [does]
typedef node * nodepointer; [point] to[?]
没有什么。它只是另一种类型的别名(标签或昵称)。它简单地说,
这也意味着任何需要
Is it necessary to use
typedef in this case?
不需要,不。你可以在任何地方使用
Is [the] expression
node * nodepointer; not equal?
不.同样,记住
这个结构是自引用的,这意味着它包含指向自身的指针。
如果您不使用标记
1 2 3 4 5 | struct node { struct node *ptr; }; // you can do this way too typdef struct node node; |
最后一个
通过
Is it necessary to use typedef in this case?
这取决于你,
Is this expression node * nodepointer; not equal?
不,这只声明
问题是,您同时要做两件事:声明结构类型和将该结构定义为名称。
对于
1 | typedef <some type> name; |
其中有些类型可能是简单的类型,如
所以
1 | typedef struct foo { int bar; } foo; |
相对应
1 | typedef <some type> name; |
其中
关于第二个问题,
在这种情况下,
1 | typedef node * nodepointer; |
将
1 2 3 4 | typedef struct node int data; struct node * next; } node; |
第一行中的
最后一行中的
这两个不一定是相同的。
如果您希望它们不同,代码如下。
1 2 3 4 | typedef struct helloNode int data; struct helloNode * next; } node; |
类型的名称是
为了更具技术性的解释,这两个
摘自http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf第6.3节
If more than one declaration of a particular identifier is visible at any point in a
translation unit, the syntactic context disambiguates uses that refer to different entities.
Thus, there are separate name spaces for various categories of identifiers, as follows:— label names (disambiguated by the syntax of the label declaration and use);
— the tags of structures, unions, and enumerations (disambiguated by following any32)
of the keywords struct, union, or enum);— the members of structures or unions; each structure or union has a separate name
space for its members (disambiguated by the type of the expression used to access the
member via the . or -> operator);— all other identifiers, called ordinary identifiers (declared in ordinary declarators or as
enumeration constants).
对于结构,您定义的是结构名(大括号前),然后是类型名(大括号后):
1 2 3 4 | typedef struct node { int data; struct node* next; } node; |
下一个创建另一个类型,一个指向节点的指针:
1 | typedef node* nodepointer; |
现在两者都可用于创建变量:
1 2 | node myNode; nodepointer aPtr; |
Daleisha正确地说,您需要struct标记来声明指向这些结构的指针
1 2 3 4 5 6 7 8 | struct node; typedef struct node node; struct node { node *next; int i; }; |
但是,这引入了更多关于一个
作为一个副作用,引入结构标记"node"使得仍然可以编写普通的
第二个typedef仍然是typedef,它不引入变量,而是引入类型名。在源代码片段中的所有声明之后,您可以说
1 2 3 | struct node *np1; node *np1; nodepointer np1; |
这些都是等效的。
两个类型名称