0

我上来学习链表。但是,我对用 struct 声明链表的几种方法感到很困惑。

这是一种方式,

typedef struct Nodetag {
int dataNum;
struct Nodetag* nextNode;
} NODE;

这是不使用 typedef 的另一种方式

struct NODE {
int dataNum;
struct NODE* nextNode;
};

我很好奇,当我们用 声明时typedef,我知道Nodetag用于让编译器知道是什么struct Nodetag* nextNode;。但是, 的实际标识符是struct什么?Nodetag还是NODE?如果是Nodetag,什么时候NODE使用?

4

4 回答 4

6

您可以选择给结构一个标签,如struct Nodetagstruct NODE。这些标签(以及联合标签和枚举标签)位于与普通标识符不同的命名空间中。

typedef版本为struct Nodetag:

typedef struct Nodetag { ... } NODE;

NowNODE是普通标识符名称空间中的类型名称,它是 . 的同义词或别名struct Nodetag

请注意,您还可以编写:

typedef struct Nodetag NODE;

struct Nodetag
{
    int   dataNum;
    NODE *nextNode;
};

第一行说“存在带有标签的结构类型,Nodetag并且NODE是该类型的别名”。第二个块说“struct Nodetag由这些项目组成”,将 aNODE *列为成员之一。


C和C++是两种不同的语言

请注意,这个问题被标记为 C,并且您得到的是直接 C 的答案(这很好)。但是,如果您遇到过 C++,您会发现:

struct Nodetag
{
    int      dataNum;
    Nodetag *nextNode;
};

Nodetag是有效的 C++ 并在普通标识符命名空间(以及(结构)标记命名空间中的标记)中生成类型名称Nodetag。这在 C 中无效。如果您最终使用 C++ 编译器编译 C,您可能会感到困惑代码,虽然。

于 2013-03-21T00:13:25.957 回答
3

这:

struct Nodetag {
    /* ... */
};

创建一个名为struct Nodetag. 同样,这个:

struct NODE {
    /* ... */
};

创建一个名为struct NODE.

在任何一种情况下,您都可以用声明包装该声明typedef,为同一类型创建第二个名称:

typedef struct S {
    /* ... */
} T;

这让您可以将类型称为 asstruct S或 as T。(你不能只调用它S——尽管如果你使用 C++ 而不是 C 编程,你可以调用它。)

编写上述内容的等效方法是:

struct S {
    /* ... */
};
typedef struct S T;

请注意,struct 标签和 typedef 名称位于不同的命名空间中(不是 C++ 意义上的“命名空间”一词),因为 struct 标签只能跟在关键字之后struct。所以没有必要区分它们。

typedef struct Node {
    /* ... */
} Node;

现在您可以将类型称为struct Node或仅称为Node.

添加这样的 typedef 并没有太大的优势;如果你喜欢,你可以省略它,只将类型称为struct Node. (但是很多 C 程序员喜欢能够为类型使用一个单词的名称,而 typedef 是唯一的好方法(a#define是另一种方法,但不是好方法。)

也可以省略标签名称,只使用 typedef:

typedef struct {
    /* ... */
} Node;

这为您提供了一个匿名结构类型,然后立即创建Node引用它的名称。但是使用这种方法,结构不能包含指向自身的指针,因为名称Node直到结构定义结束后才可见。

于 2013-03-21T00:16:15.247 回答
0

第一个结构被调用struct Nodetag,第二个结构被调用struct NODE

在第一个实例中,已经定义了一个 typedef 为 的“别名” NODEstruct Nodetag但它不会更改结构的名称。例如,它的作用是让您输入,NODE*而不是struct Nodetag*. 这是简写​​,仅此而已。

于 2013-03-21T00:09:51.667 回答
0

结构标签和类型存在于不同的命名空间中。你可以有一个struct node也可以有一个类型node。结构标签必须与说明struct符/前缀一起使用以区分它们。当你这样做时:

typedef struct Nodetag {
int dataNum;
struct Nodetag* nextNode;
} NODE;

您正在定义一个新类型并定义一个结构标记,但您实际上并不需要定义一个类型,这只是为了方便。在结构定义中,由于编译器在读取部分之前不知道类型,因此} NODE;您必须使用结构标签来引用您正在定义的结构。

于 2013-03-21T00:12:52.867 回答