指向结构内其他结构的指针

时间:2016-10-20 12:26:51

标签: c pointers data-structures struct

我的讲师提出了以下一段代码,但对其所代表的内容的解释不充分。

typedef struct _s {
    int         value;
    struct _s   *next;
}  STACKITEM;

STACKITEM    *stack = NULL;
  1. 我理解指针和结构是什么。但是,我不知道在结构中有一个指向结构的指针意味着什么。请澄清并详细说明这一概念。

  2. 我不明白为什么结构被声明为typedef。由于以下原因,这似乎是多余的:

  3. 典型结构如下:

    struct struct_format_name { 
    members;
    } individual_struct_object_name;
    

    因此,我们已经声明一个对象是一个结构,并且给定了一个结构名称为_s的格式。那么使用typedef有什么意义呢?除了typedef关键字之外,它与用于声明任何结构的格式相同。

    1. 我想澄清指向结构化格式的结构的指针(如上所述)与指向特定结构的结构的指针之间的区别。
    2. 我怀疑指向结构化格式的结构的指针,如上所述,可以指向该格式的任何结构?但是,指向具体结构的结构的指针只能指向该特定结构,而不是指向相同格式的其他结构?

4 个答案:

答案 0 :(得分:4)

这称为链表。指针next允许您通过让每个元素指向下一个元素来浏览列表,并让最后一个元素指向next指向NULL,这样您就可以知道了#39}最后。请参阅https://en.wikipedia.org/wiki/Linked_list您实际上并未存储结构,而是存储指向下一个元素的指针,将其视为一个数组,但是在不是对齐的元素的情况下,它们中的每一个都指向改为使用其地址的下一个元素。

对于next指针,使用struct关键字声明它的原因是STACKITEM类型尚不存在(它在结构的定义之后定义)

答案 1 :(得分:2)

  

典型结构声明如下。

只有你永远不想再创造一个。您正在质疑的语法是声明结构的典型方法。

typedef允许您使用较短的名称struct_format_name而不是struct struct_format_name来引用它。

答案 2 :(得分:1)

  

我理解指针和结构是什么。但是,我不明白在结构中有一个指向结构的指针意味着什么。请澄清并详细说明这一概念。

这是一个称为 singly linked list 的数据结构的常见C实现,其中列表中的每个元素都明确指向以下元素。在这种情况下,struct _s的每个实例都指向struct _s的另一个实例,如下所示:

+---+---+         +---+---+        +---+---+
|   |   | ----->  |   |   | -----> |   |   |
+---+---+         +---+---+        +---+---+
                                     ^   ^
                                     |   |
                                     |   +---- next
                                     +-------- value

您可以使用链接列表结构实现stack,这是您的教师正在做的事情。 A"推"操作将动态创建一个新的STACKITEM,将整数值保存到它,并使新的STACKITEM成为列表的头部(a.k.a.堆栈的顶部)。 stack指针始终指向列表中的第一个元素(如果列表为空,则为NULL。)

stack: |||

push( &stack, 1 );

       +---+---+
stack: | 1 |   |---|||
       +---+---+

重复调用push会在列表的开头添加一个新元素:

push( &stack, 2 );

       +---+---+    +---+---+
stack: | 2 |   |--->| 1 |   |---|||
       +---+---+    +---+---+

push( &stack, 3 );

       +---+---+    +---+---+    +---+---+
stack: | 3 |   |--->| 2 |   |--->| 1 |   |---|||
       +---+---+    +---+---+    +---+---+

代码看起来像

void push( STACKITEM **stack, int value )
{
  STACKITEM *newItem = malloc( sizeof *newItem );
  if ( newItem )
  {
    newItem->value = value;
    newItem->next  = *stack;    // newItem now points to former top of stack
    *stack         = newItem;   // newItem is now the top of the stack
  }
}

A" pop"操作只是反向运行 - 它通过将stack指针设置为指向下一个元素并释放该元素的内存来删除列表的第一个元素:

void pop( STACKITEM **stack )
{
  STACKITEM *top = *stack;
  if ( top )
  {
    *stack = top->next;
    free( top );
  }
}

pop( &stack );

       +---+---+    +---+---+
stack: | 2 |   |--->| 1 |   |---|||
       +---+---+    +---+---+

pop( &stack );

       +---+---+
stack: | 1 |   |---|||
       +---+---+

pop( &stack );

stack: |||
  

我不明白为什么结构被声明为typedef。由于以下原因,这似乎是多余的:

typedef有两个基本目的:

  1. 简化复杂类型名称
  2. 摘要实施细节
  3. 在这种情况下,您的教师的目标是2 - 抽象出堆栈项类型的struct - ness。不幸的是,如果您作为该类型的用户必须了解实现细节,那么这并不是为了达到目的。

    注意:您的教师不应在标签名称中使用前导下划线;具有前导下划线的标识符保留供实现使用。

答案 3 :(得分:0)

结构中的指针与结构外部的指针没有区别,指向结构类型的指针可以指向该类型的任何对象。

无法定义只能指向特定对象的类型。

您的代码和讲师的代码没有完成同样的事情,所以没有冗余 你要定义一个类型和一个对象;他们为这种类型定义了一种类型和一个不同的名称 (听起来有点像你把对象混淆了。)

他们的typedef并非绝对必要,但这是一种非常常见的方法,可以避免在使用结构类型时输入struct

你的变体非常典型的 类型通常是全局定义的,而变量尽可能在本地声明。