C - 重新分配作为结构属性的指针:取消引用不完整类型的指针

C - reassigning pointer which is attribute of struct: dereferencing pointer to incomplete type

我相当确定我对 C 中的指针的理解很糟糕(至少在语法上)。

我正在尝试创建一个包含大量数据的 linkedlist 结构。后来,我尝试添加一个新结构作为那个 linkedlist 的头部,指向旧头部,它有一个 "prior" link 指向新头部。

typedef struct{
  int sequence_number;
  int file_descriptor;
  FILE *requested_file;
  int bytes_remaining;
  int quantum;
  struct RCB *next;
  struct RCB *prior;
} RCB;

   RCB *RRhead;
...


function blah(){
  RCB new_rcb = {sequence_counter, fd, fin, new_bytes_remaining, new_quantum, RRhead, NULL};
  RRhead->prior = &new_rcb;
  RRhead = &new_rcb;
  sequence_counter++;
}

我收到这些错误:

sws.c: In function ‘admit_to_scheduler_RR’:
sws.c:317:3: warning: initialization from incompatible pointer type [enabled by default]
   RCB new_rcb = {sequence_counter, fd, fin, new_bytes_remaining, new_quantum, RRhead, NULL};
sws.c:317:3: warning: (near initialization for ‘new_rcb.next’) [enabled by default]
sws.c:318:17: warning: assignment from incompatible pointer type [enabled by default]
   RRhead->prior = &new_rcb;

这是问题的一部分。

初始化 new_rcb 时不要使用 *RRhead。你只想要 RRhead.

该结构有一个指针,即 struct RCB *prior 所以你必须使用指针 RRhead

首先,RRhead 只是一个指针,所以当你进入 RRhead->prior 时,你会得到一个运行时错误,因为 RRhead 没有指向任何东西(RRhead->prior 说“获取 'prior'属性 RRhead 指向的 RCB 结构)

其次,当你将*RRhead作为new_rcb的最后一个初始化器传递时:prior是一个RCB指针,RRhead是一个RCB指针。它们是相同的类型,因此无需进行任何引用或取消引用,只需传递 RRhead。这将使 new_rcb 的先验 属性 指向当时 RRhead 指向的任何内容(此时什么都没有,因为 RRhead 尚未初始化为任何值)

第三,RRhead->prior = new_rcb;是错误的,因为 'prior' 是 RCB 指针,而 new_rcb 不是指针,而是 RCB。传递 new_rcb 的地址,转到 RRhead->prior = &new_rcb;

最后,您不太可能希望 new_rcb 被静态分配。

RCBstruct RCB是两种完全不同的、不相关的类型。 struct RCB 从未在您的代码中定义,因此不完整。

要使它们合二为一,写

typedef struct RCB {
   ....
} RCB;

这里有很多问题。由于您一直在更改它,所以不清楚您的真实代码到底是什么,但我会破解的:


首先,在 C 语言中,struct 标签在一个单独的 "namespace" 到 typedef 名称中。 struct RCBRCB 之间没有关系。特别是,在这段代码中:

typedef struct {
  struct RCB *next;
  struct RCB *prior;
} RCB;

next 不指向 RCB。它指向一个 struct RCB,它是一个与 RCB 完全不同的类型。这就是您收到错误 error: dereferencing pointer to incomplete type 的原因。您从未定义 struct RCB 是什么。

如果您想要一个包含指向自身的指针的结构,您必须使用结构标记,因为在 typedef 完成之前 typedef 名称不存在。例如:

struct RCB
{
    // ...
    struct RCB *next, *prior;
};

typedef struct RCB RCB;

当然,typedef 是可选的; 可以与结构定义结合,但我认为将两者分开更清楚。


下一个问题是:

new_rcb = {sequence_counter, fd, fin, new_bytes_remaining, new_quantum, RRhead, NULL};

这在C中是不允许的,赋值运算符的右边必须是一个表达式。大括号括起来的列表不是表达式。避免此问题的最简单方法是使用初始化:

RCB new_rcb = {sequence_counter, fd, fin, new_bytes_remaining, new_quantum, RRhead, NULL};

最新编辑中暗示了另一个运行时问题:

function blah(){
  RCB new_rcb = {sequence_counter, fd, fin, new_bytes_remaining,  new_quantum, RRhead, NULL};
  RRhead->prior = &new_rcb;
  RRhead = &new_rcb;
  sequence_counter++;
}

显然这是某种伪代码。但是 new_rcbblah 函数的局部变量。 new_rcbblah returns 时停止存在。这意味着 RRhead 指向的列表将包含一个悬挂指针。

使用指针时,您需要非常清楚地了解指针指向的位置以及所指向对象的生命周期。

要解决此问题,您可以使用动态分配 (malloc) 或某种内存池。