为什么在C中的struct声明中使用typedef名称两次?

Com*_*PVT 12 c struct typedef

在研究C中的队列时,我遇到了类似于下面的示例.为什么结构在大括号的开头和之后都命名?为什么在添加相同类型的项时,结构类型在结构内部再次使用?这些事情是多余的还是有意义的?

typedef void* vpoint_t;

typedef struct queue_item_t{
  vpoint_t void_item;
  struct queue_item_t* next;
} queue_item_t;
Run Code Online (Sandbox Code Playgroud)

Jon*_*art 17

typedef struct queue_item_t {     // 1
  vpoint_t void_item;
  struct queue_item_t* next;      // 2
} queue_item_t;                   // 3
Run Code Online (Sandbox Code Playgroud)

首先,请注意这整个陈述是定义一个typedef.

3)说我们正在定义(via typedef)的新类型被命名queue_item_t.

1)命名结构的名称(正如我们所说的那样给出一个新名称)struct queue_item_t.这是它的全名,包括struct在前面.

2)由于新的类型还不存在(请记住,我们仍然在定义它的过程中),我们不得不使用它迄今唯一的名称,这是struct queue_item_t1) .


请注意,您可以使用匿名struct定义,这样可以省略1)中的名称.一个简单的例子:

typedef struct {
   int x, y, z;
} vector3;
Run Code Online (Sandbox Code Playgroud)

但是,在您的示例中,由于我们需要结构能够引用自身,因此next指针必须具有已定义的类型.我们可以通过前面声明 struct,typedefing然后使用typedefd类型定义struct来实现next:

struct _queue_item;                           // 4

typedef struct _queue_item queue_item_t;      // 5

struct _queue_item {                          // 6
  vpoint_t void_item;
  queue_item_t* next;                         // 7
}
Run Code Online (Sandbox Code Playgroud)

4)声明struct _queue_item存在,但尚未提供它的定义.

5) Typedef queue_item_tstruct _queue_item.相同.

6)现在给出结构的定义......

7) ...使用我们的typedef'd queue_item_t.


所有这一切......在我看来,请不要使用typedef作为结构.

struct queue_item {
    void *data;
    struct queue_item *next;
}
Run Code Online (Sandbox Code Playgroud)

简单而完整.您可以设法键入这六个额外的字符.

Linux内核编码风格:

第5章:Typedef

请不要使用"vps_t"之类的东西.将typedef用于结构和指针是错误的.当你看到一个

  vps_t a;
Run Code Online (Sandbox Code Playgroud)

在源头,这是什么意思?相反,如果它说

  struct virtual_container *a;
Run Code Online (Sandbox Code Playgroud)

你实际上可以告诉"a"是什么.

有一些例外情况,您可以阅读.


最近的一些相关问题:


Joh*_*ode 5

让我们稍微更改一下声明,使讨论更容易进行:

typedef struct queue_item {
  vpoint_t void_item;
  struct queue_item* next;
} QueueItemType;
Run Code Online (Sandbox Code Playgroud)

C支持几种不同的名称空间;为联合,结构和枚举类型上的标记名称保留一个名称空间。在这种情况下,标签名称为queue_item。另一个名称空间为常规标识符保留,包括typedef名称,QueueItemType

next成员用于指向另一个类型的实例struct queue_item(即队列中的下一个项目)。声明它为的指针struct queue_item有两个原因:

  • struct类型不能包含其自身的实例;一方面,类型必须无限大(struct queue_item包含一个member next,这是一个struct queue_item包含member next,这是a struct queue_item包含一个member nextad infinitum);

  • 直到close ,结构类型定义才完整},您不能声明不完整类型的实例。但是,您可以声明一个不完整类型的指针,我们将在下面进行操作:

    struct queue_item *下一步;

为什么不使用QueueItemType *next;代替struct queue_item *next?同样,结构类型定义在声明时还不完整next。typedef名称QueueItemType尚不存在。但是,标记名称queue_item已经对编译器可见,因此我们可以使用type声明指针struct queue_item

由于标记名称和typedef名称占用不同的名称空间,因此可以将相同的名称用于标记名称和typedef名称而不会发生冲突。编译器通过struct关键字的存在来消除两者之间的歧义。