在C中,添加到FIFO队列后部时遇到问题,请参考最后一个元素

在C中,添加到FIFO队列后部时遇到问题,请参考最后一个元素,c,linked-list,fifo,C,Linked List,Fifo,我很难理解C语言。我正在尝试实现一个FIFO链表,在这个链表中我有一个对列表末尾的引用,以便在添加元素时轻松访问。在头部和后部为同一节点的情况下,排队到空列表可以很好地工作。但是,当我第二次排队时,后面是正确的新节点,但头部也会更新,应该保持不变。有没有想过我可能做错了什么?如果它很难阅读,我为一行条件提前道歉 typedef struct node { PCB *pcb; struct node *next; }Node; typedef struct queue {

我很难理解C语言。我正在尝试实现一个FIFO链表,在这个链表中我有一个对列表末尾的引用,以便在添加元素时轻松访问。在头部和后部为同一节点的情况下,排队到空列表可以很好地工作。但是,当我第二次排队时,后面是正确的新节点,但头部也会更新,应该保持不变。有没有想过我可能做错了什么?如果它很难阅读,我为一行条件提前道歉

typedef struct node {
    PCB *pcb;
    struct node *next;
}Node;

typedef struct queue {
    Node *head, *rear;
    int size;
}Queue;

Queue * enqueue (Queue *queue, PCB *pcb) {

    // Ready a new node to add to list:
    Node node = {pcb, NULL};

    // Node becomes head in empty list, otherwise appended to rear.
    queue->size == 0 ? (queue->head = queue->rear = &node) : (queue->rear = &node);

    // Keep track of list size
    queue->size++;

    return queue;
}
更新:

Queue * enqueue (Queue *queue, PCB *pcb) {


    // Ready a new node to add to list:
    Node *node = malloc(sizeof(Node));
    node->pcb = pcb;
    node->next = NULL;

    // Node becomes head in empty list, otherwise appended to rear.
    queue->size == 0 ? (queue->head = queue->rear = node) : (queue->rear->next = node);

    // New node always becomes the new rear node
    queue->rear = node;

    // Keep track of list size
    queue->size++;

    return queue;
}
试试这个

#include <stdlib.h>
typedef struct node {
  PCB *pcb;
  struct node *next;
} Node;

typedef struct queue {
  Node *head, *rear;
  int size;
} Queue;

Queue *enqueue ( Queue *queue, PCB *pcb ) {
  if ( queue->size == 0 ) {
    queue->head = queue->rear = malloc( sizeof( Node ) );
  }
  else {
    queue->rear->next = malloc( sizeof( Node ) );
    queue->rear = queue->rear->next;
  }
  queue->rear->pcb = pcb;
  queue->rear->next = NULL;
  queue->size++;
  return queue;
}
#包括
类型定义结构节点{
PCB*PCB;
结构节点*下一步;
}节点;
typedef结构队列{
节点*头部,*后部;
整数大小;
}排队;
队列*排队(队列*队列,PCB*PCB){
如果(队列->大小==0){
队列->头部=队列->后部=malloc(节点大小);
}
否则{
队列->后方->下一步=malloc(sizeof(节点));
队列->后方=队列->后方->下一步;
}
队列->后部->pcb=pcb;
队列->后方->下一步=NULL;
队列->大小++;
返回队列;
}
但是使用C++会更安全、更容易。记住以后要
free()
你的笔记


对于文档(参见注释):问题中第一种方法的错误是保留了局部变量的指针。它位于堆栈上,但仅在函数终止之前有效。终止后,它是指向堆栈上某个位置的指针。使用足够的局部变量调用下一个函数时,将立即覆盖此位置。解决方案是在堆上分配。

将第一个节点添加到队列时,更新的代码不太正确,因为行
队列->头部->下一个=队列->后部
设置
node->next=node
,而不是将其设置为
NULL
。另外,新的
rear
始终是新节点,可以在
if/else
语句之外设置

Queue * enqueue (Queue *queue, PCB *pcb) {

    // Ready a new node to add to list:
    Node *node = calloc(1, sizeof(Node));
    node->pcb = pcb;
    node->next = NULL;

    // Node becomes head in empty list, otherwise appended to rear.
    if (queue->size == 0) {
        queue->head = node;
    } else {
        queue->rear->next = node;
    }
    queue->rear = node;

    // Keep track of list size
    queue->size++;

    return queue;
}

在队列中存储局部变量的地址<代码>节点从
排队
返回后将超出范围,并将队列指针指向无效内存。请显示对M Oehm注释的.complete:如果声明
静态节点={pcb,NULL}您的代码可能会工作,因为在整个程序执行过程中,
节点
将存在,而不仅仅是在
排队
函数`@MichaelWalz:中,队列将由相同的节点组成。我不认为你可以在这里轻松地在堆上分配内存(或创建一个节点池)。@MOehm-true实际上是这样。在我看到这篇文章之前,我在意识到我的代码实际上没有正确分配下一个节点后,对我的代码进行了修复。但实际上我更喜欢你的。谢谢但是看看C++和STL容器。这使得动态数据结构变得简单。补充:我犯了错误,用C++编译器编写这个C示例。因此,如果不强制转换,您将得到从“void*”到“node*”的
无效转换。但是如果你写C,你应该使用C编译器。在这种情况下,不铸造是更好的做法,也更安全(例如,看看为什么)。因此,我更新了答案。那么应该改为
queue->head=queue->rear=node