C语言中,结构体定义中的指向另一个结构体的指针该如何声明?

61

如何在结构体定义中使用指针指向下一个结构体:

typedef struct A {
  int a;
  int b;
  A*  next;
} A;

这是我最初写的方式,但它不起作用。


注意 C11 §6.7.2.1 结构体和联合体说明符 ¶3结构体或联合体不得包含具有不完整或函数类型的成员(因此,结构体不得包含自身的实例,但可以包含指向自身实例的指针),... - Jonathan Leffler
6个回答

85

你可以在一条语句中定义typedef并前置声明结构体,然后在后续的定义中定义结构体。

typedef struct A A;

struct A
{
    int a;
    int b;
    A* next;
};

编辑:正如其他人所提到的,如果没有前向声明,在结构定义内部结构名称仍然是有效的(即可以使用struct A),但是在typedef定义完成之前,typedef不可用(因此仅使用A无效)。如果只有一个指针成员,这可能并不太重要,但如果您有具有许多自我类型指针的复杂数据结构,则可能不太方便。


1
这是做这件事的“规范”方式。 - unwind
14
解压:许多 C 代码风格规范都强烈反对 typedef 结构体。我不会说这是经典的。 - Chris Young
2
如果我可以为评论投票,Chris Young 将获得 +1。本地类型和聚合结构之间存在巨大差异。不要将其隐藏在 typedef 后面。 - ephemient
3
为什么我不应该把它隐藏起来?它们只是实现细节。 - YoTengoUnLCD
1
@turner:因为在“struct A”中,一个“A”表示结构类型,而第二个“A”给类型命名(别名)为“A”。如果你有“typedef int B;”,那么“int”是类型,“B”是类型的新名称。同样,使用“typedef struct A A;”,则“struct A”是类型,“A”是类型的新名称。 - Jonathan Leffler
显示剩余2条评论

68

除了第一个答案之外,不使用typedef和前向声明,这种写法也可以。

struct A 
{ 
    int a; 
    int b; 
    struct A *next; 
};

没有typedef,你实际上知道你在代码中处理的是一个结构体。 - Greg Schmit

21

A*之前缺少struct

  typedef struct A {
    int a;
    int b;
    struct A* next;
  } A;

14

您可以不使用前向声明:

struct A {
    int a;
    int b;
    struct A *next;
};

9

请注意,您正在使用C语言,而不是C++。

如果您真的必须要typedef一个结构体(而我与大多数程序员一起工作的人不会这样做¹),请按照以下方式进行:

typedef struct _A {
    int a;
    int b;
    struct _A *next;
} A;

为了清楚区分_A(在结构体命名空间中)和A(在类型命名空间中),需要进行明确的区分。
¹typedef会隐藏指针所指向的类型的大小和存储方式,但一些人认为在像C这样的低级语言中,试图隐藏任何东西都是有害且适得其反的。因此,建议在需要使用struct A时,请坚持输入完整的命名空间前缀。


2
"struct A" 如何告诉我有关其大小的信息? - quant_dev
它告诉你它是一个聚合结构,因此许多事情如将其作为参数传递、返回它、比较和a = b都是低效或不起作用的。 - ephemient
4
A是一个保留的名称。A_可以。 - MSalters
2
吹毛求疵:A是一个不好的名称:前导下划线属于编译器。编辑:该死,我想我刚刚回应了MSalters的话。 - Bernd Jendrissek
2
我在所有编程时间中从未遇到过因为给结构体和typedef相同的名称而导致的问题,只有在这种情况下(链表等),我才会费心给结构体命名。 我认为你只是在散布恐惧。 你能举个例子说明为什么给两者相同的名称会导致问题吗? 此外,我从来没有遇到过在所有结构体上使用typedef导致任何问题,所以我觉得你认为它“有害并且低效”有点过了。 - Wayne Uroda
显示剩余2条评论

0
typedef struct {
 values
} NAME;

这是一种更短的方式来定义结构体,我认为这是最简单的符号表示法,只需将名称放在前面而不是后面。

然后你可以像这样调用它

NAME n;  

NAME *n; // if you'd like a ptr to it.

这种方法有什么问题吗?


2
正如问题所述,需要在结构体(链表)内部有一个指针,因此我不明白你的回答有什么作用。 - claf

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接