用结构体理解 typedef

Ske*_*lio 3 c struct typedef

我很难理解这个代码示例:

typedef struct node
{
        int data;
        struct node * next;
} node;

typedef node * nodepointer;
Run Code Online (Sandbox Code Playgroud)

所以,我们正在使用 typedef 构建结构节点......我假设我们这样做是为了在不需要“struct”关键字的情况下初始化结构。

我想问一下为什么在结构定义中我们使用了两次名称“节点” (在开始和结束时)。

其次typedef node * nodepointer;指向什么。在这种情况下是否有必要使用 typedef?这个表达式node * nodepointer;不相等吗?

Qix*_*Qix 5

首先,让我们在这里明确一点:atypedef不是变量的声明。它只是将新类型名称别名为现有类型说明符。

typedef <type specifier> new_type_name;
Run Code Online (Sandbox Code Playgroud)

所以这里发生的事情对于未经训练的人来说肯定是骗人的。

struct node本身是一个具有两个属性和一个的struct调用。nodeint datastruct node *next

我稍后会详细介绍next,但现在这很简单。

然后,周围的环境typedef采用该结构并将其命名为node。你可能会问,这是为什么?

这是因为在 C(与 C++ 不同)中,通过标记名称使用结构需要在类型前加上struct.

struct Foo {
    // ...
};

Foo bar; // ERROR
struct Foo bar; // OK
Run Code Online (Sandbox Code Playgroud)

使用 typedef,我们使用typename为结构命名,称为node。这个例子应该让它更清楚一点。

typedef struct Foo {
    // ...
} FooType;

Foo bar; // ERROR
struct Foo bar; // OK

FooType bar; // OK
struct FooType bar; // ERROR
Run Code Online (Sandbox Code Playgroud)

请记住,您可以定义没有标签的结构,因此也可以定义typedef它们。

typedef struct {
    // ...
} FooType;

FooType bar; // OK
Run Code Online (Sandbox Code Playgroud)

虽然我会解释为什么你不能在你的例子中做到这一点。

struct node *next您示例中的属性是不完整的 type。简单地说,不完整类型是已声明(给定名称和类型,即struct node;)但未定义(给定“主体”,即struct node { int foo; };)的类型。

不完整的类型在定义之前不能使用,除非您指向它们

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.
Run Code Online (Sandbox Code Playgroud)

因此,通过类型struct node *next声明,我们已经拥有了声明struct node,但不是定义,这使得一个指向struct node可能的。

您也可以推断,那就是,通过struct node直接将工作:

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)
};
Run Code Online (Sandbox Code Playgroud)

回答您的最后三个问题:

[什么] typedef node * nodepointer;[指向] [?]

没有。它只是另一种类型的别名(标签或“昵称”)。它只是说该类型nodepointer实际上是一个node *.

这也意味着任何需要 a 的东西都node *可以使用 a nodepointer,反之亦然。

typedef在这种情况下有必要使用吗?

没有必要,没有。你也可以在node *任何地方使用而不是nodepointer. 大多数编码标准都不赞成将typedef类型转换为它们的指针类型(如您的示例),因为它增加了代码库的混乱(正如您在这个问题中所证明的那样!:))

[the] 表达式node * nodepointer;不相等吗?

不。同样,记住typedef只是指定另一种引用相同类型的方法。它实际上并不创建任何内存,而是为现有类型赋予新名称。