为什么我需要使用 & 将指针传递给此堆栈实现中的结构

Why do I need to use & to pass a pointer to a struct in this stack implementation

在下面的程序中,我需要使用 &-operator 将参数传递给函数,尽管我希望它是一个指针,而函数需要一个指针。为什么我需要这样做?

程序在C中使用链表和不完全类型实现了一个简单的堆栈。以下是三个必要的文件:

stack.h

#ifndef STACK_H
#define STACK_H

#include <stdbool.h>

struct Stack {
        int number;
        struct Stack *next;
};

/*
 * We declare a pointer to a Stack structure thereby making use of incomplete
 * types. Clients that pull in stack.h will be able to declare variables of type
 * pstack which are pointers to Stack structures. */
typedef struct Stack *pstack;

bool is_empty(pstack *s);
void make_empty(pstack *s);
void push(pstack *s, int new_num);
int pop(pstack *s);

#endif /* STACK_H */

stack.c

#include <stdio.h>
#include <stdlib.h>
#include "stack.h"

bool is_empty(pstack *s)
{
        return !s;
}

void make_empty(pstack *s)
{
        if (!is_empty(s))
                pop(s);
}

int pop(pstack *s)
{
        struct Stack *tmp;
        int i;

        if (is_empty(s)) {
                exit(EXIT_FAILURE);
        }
        tmp = *s;
        i = (*s)->number;
        *s = (*s)->next;
        free(tmp);
        return i;
}

void push(pstack *s, int new_num)
{
        struct Stack *new_node = malloc(sizeof(struct Stack));
        if (!new_node) {
                exit(EXIT_FAILURE);
        }
        new_node->number = new_num;
        new_node->next = *s;
        *s = new_node;
}

stackclient.c

#include <stdio.h>
#include <stdlib.h>
#include "stack.h"

int main(void)
{
  pstack s1;
  int n;

  push(&s1, 1);
  push(&s1, 2);

  n = pop(&s1);
  printf("Popped %d from s1\n", n);
  n = pop(&s1);
  printf("Popped %d from s1\n", n);

  exit(EXIT_SUCCESS);
}

同样,我认为通过使用

typedef struct Stack *pstack;

之后在 main()

pstack s1;

我正在声明一个指向链表 Stack 的指针,因此只需使用

s1 传递给 say push() 就可以了
push(s1, 1);

但我实际上需要使用

push (&s1, 1);

为什么?

你的函数都被声明为以pstack*作为参数,它实际上是一个指向Stack结构体的指针。只需使用 pstack。您还需要在这些函数的实现中将 (*s) 的实例替换为 s

编辑: 正如评论中指出的那样,您实际上在函数实现中写入 (*s) 并依赖于此行为的正确性,因此您需要将参数保持为 pstack*。从概念上讲,这是因为堆栈变量 (s1) 实际上是堆栈本身的顶部,因此必须由 pushpop.

修改

您需要在void push(pstack *s, int new_num)中使用pstack *s(指向pstack的指针),根据您的实现代码, 如果使用 pstack s( pstack ),new_node 将不会正确返回。

push()中插入节点的两种可能方式:

  1. 如果插入到头部,应该是*s = new_node
  2. 如果插入到尾部,可以是s->next = new_node

回到代码,如果要使用push(s1, 1);比如,

 //If only use pstack s, the new_node can not be pushed.
 void push(pstack s, int new_num) //it is a wrong implementation for demo
 {
        struct Stack *new_node = malloc(sizeof(struct Stack));
        if (!new_node) {
                exit(EXIT_FAILURE);
        }
        new_node->number = new_num;
        new_node->next = s;
        s = new_node;// WRONG! here, the new_node cannot be kept by s
                     // two typical node insert ways:
                     // 1)if insert to head, it should be *s = new_node
                     // 2)if insert to tail, it could be s->next = new_node
                     //Now, Your code applied the #1 way, so need *s 
 }

所以,应该输入pstack *s,调用push (&s1, 1);

 void push(pstack *s, int new_num)//it is the correct version the same as your post
 {
        struct Stack *new_node = malloc(sizeof(struct Stack));
        if (!new_node) {
                exit(EXIT_FAILURE);
        }
        new_node->number = new_num;
        new_node->next = *s;
        *s = new_node;//here, the new_node could be kept by *s
 }