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

时间:2015-09-04 19:27:37

标签: 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;

4 个答案:

答案 0 :(得分:16)

typedef struct queue_item_t {     // 1
  vpoint_t void_item;
  struct queue_item_t* next;      // 2
} queue_item_t;                   // 3

首先,请注意,整个语句定义了typedef

3)说我们正在定义的新类型(通过typedef)是转到被命名为queue_item_t

1)结构的名称(正如我们所说的那样被赋予一个新名称)被命名为struct queue_item_t。这是它的全名,包括前面的struct

2)因为新类型还没有存在(请记住,我们仍然在定义它的过程中),我们必须使用它所拥有的唯一名称远,struct queue_item_t,来自 1)

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

typedef struct {
   int x, y, z;
} vector3;

但是,在您的示例中,由于我们需要结构能够引用自身,因此next指针必须具有已定义的类型。我们可以通过转发声明结构,键入它,然后使用typedef的{​​{1}} d类型定义结构来实现:

next

4)声明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 } 存在,但尚未提供定义。

5) Typedef struct _queue_itemqueue_item_t相同。

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

7) ...使用我们的struct _queue_item' d typedef

所有这一切......在我看来,please don't use typedefs for structs

queue_item_t

简单而完整。您可以设法输入这六个额外字符。

来自Linux Kernel coding style

  

第5章:Typedef

     

请不要使用像" vps_t"这样的内容。       错误使用typedef作为结构和指针。当你看到

struct queue_item {
    void *data;
    struct queue_item *next;
}
     

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

  vps_t a;
     

你实际上可以告诉他们" a"是

有一些例外,你可以阅读。

最近的一些相关问题:

答案 1 :(得分:4)

让我们稍微改变声明,使讨论更容易理解:

typedef struct queue_item {
  vpoint_t void_item;
  struct queue_item* next;
} QueueItemType;

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

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

  • 结构类型不能包含自身的实例;一方面,类型必须无限大(struct queue_item包含一个成员next,这是一个struct queue_item,其中包含一个成员next,它是一个struct queue_item 1}}包含成员next ad infinitum );

  • 结构类型定义不是完成直到结束},并且您无法声明实例不完整的类型。但是,您可以将指针声明为不完整的类型,我们将在下面执行此操作:

    struct queue_item * next;

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

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

答案 2 :(得分:0)

首先,我建议不要使用结构名称和相同的类型名称。使用typedef struct QUEUE_ITEM {...} queue_item_t;

关于问题:如果你想创建一个"递归数据结构",即一个指向自身实例的数据结构,那么你必须能够告诉编译器&# 34;这个字段是指向我们自己的一个指针。你还不完全知道我们的样子,因为我还在定义它,所以只需为指针保留空间"。要做到这一点,你宣布

struct T {
    ...
    struct T *ptr;
    ....
};

使用最终} queue_item_t;,您可以为结构创建新名称。

答案 3 :(得分:0)

" struct foo {...}"是一回事。它定义了一个结构,你需要键入" struct foo"在你使用它的每个地方。

" typedef ... foo"定义一个新类型,所以你只需键入" foo"在哪里使用它。

" typedef struct foo {...} foo"是一个成语,所以你可以使用两者,很可能只是" foo"以节省击键和视觉污染。