C中解引用void*指针

5

我是C语言的新手,我的第一个项目需要实现基于数组的队列。

我希望我的队列能够容纳任何类型的对象,因此我创建了一个QueueElement结构体来保存指向任何类型对象的void指针。我认为一切都正常工作,但是我无法读取QueueElement结构体中的'position'和'value'字段。当我尝试编译时,会出现以下错误:

错误:

Runnable.c: In function `main':
Runnable.c:10: error: dereferencing pointer to incomplete type
Runnable.c:11: error: dereferencing pointer to incomplete type

我相信我只是没有正确地投掷。任何帮助都将不胜感激。

再次感谢, Pooch

Runnable.c

   #include <stdio.h>
    #include "Queue.h"
    
    int main(void) {
            int i = 9;
            Queue q = CreateQueue();
            QueueElement e = CreateQueueElement(&i);
            Enqueue(q, e);
            QueueElement f = Dequeue(q);


            /* PROBLEM IS HERE */
            printf("position: %d", f->position);
            printf("value: %d", (int *)(f->value));
            DestroyQueue(q);
            return 0;
    }

Queue.h

#ifndef QUEUE_H
#define QUEUE_H

#include "QueueElement.h"

typedef struct QueueStruct *Queue;

Queue CreateQueue(void);

void DestroyQueue(Queue q);

void Enqueue(Queue q, QueueElement e);

QueueElement Dequeue(Queue q);

#endif

Queue.c

#include "QueueElement.h"
#include "Queue.h"

#define QUEUE_SIZE 10

struct QueueStruct {
        QueueElement contents[QUEUE_SIZE];
        int size;
};

Queue CreateQueue(void) {
        Queue q = malloc(sizeof(struct QueueStruct));
        q->size = 0;
        return q;
}

void DestroyQueue(Queue q) {
        int i;
        for(i = 0; i < q->size; i++) {
                free(q->contents[i]);
        }
        free(q);
}

void Enqueue(Queue q, QueueElement e) {
        if (q->size < QUEUE_SIZE) {
                q->contents[q->size++] = e;
        }
}

QueueElement Dequeue(Queue q) {
        if (q->size > 0) {
                return q->contents[--q->size];
        }
        return;
}

QueueElement.h

#ifndef QUEUE_ELEMENT_H
#define QUEUE_ELEMENT_H

typedef struct QueueElementStruct *QueueElement;

QueueElement CreateQueueElement(void *v);

void DestroyQueueElement(QueueElement e);

int GetPosition(QueueElement e);

#endif

QueueElement.c

#include <stdio.h>
#include "QueueElement.h"

struct QueueElementStruct {
        int position;
        void *value;
};

QueueElement CreateQueueElement(void *v) {
        QueueElement e = malloc(sizeof(struct QueueElementStruct));
        e->position = 0;
        e->value = v;
        return e;
}

void DestroyQueueElement(QueueElement e) {
        free(e);
}

int GetPosition(QueueElement e) {
        return e->position;
}
2个回答

6

QueueElementStruct的定义必须在Runnable.c中可见,以便能够访问它的字段。您可以将QueueElementStruct放入一个头文件中,然后在Runnable.cQueueElement.c中包含该头文件。另外,您也可以使用您的GetPosition函数并添加一个GetValue函数,并从Runnable.c中使用它们而不是直接访问字段。


Runnable.c 包含 Queue.h,而 Queue.h 又包含 QueueElement.h。这种包含关系是否有效? - Pooch
1
它确实有作用,但 QueueElement.h 并没有定义 QueueElementStruct 的成员,它只是暗示其存在。如果我包含 QueueElement.h,我只知道有一个名为 QueueElementStruct 的结构体,而不知道它的组成部分。只有 QueueElement.c 知道 QueueElementStruct 的成员是什么。 - Logan Capaldo
Logan,我使用了你和Jerry的建议,我的代码编译成功了。谢谢你们的帮助。 - Pooch

4
你需要将 void * 转换回指向“真实”类型的指针才能对其进行解引用操作。例如,如果你有一个 int,你可以取它的地址并将其放入队列中。要查看该 int,你需要将其强制转换回 int *。跟踪真实类型可能很棘手(通常是如此),例如创建一个所有要放入集合中的类型的枚举,并将每个项目与其中一个相关联。
正因为如此,C++(例如)只选择将一种类型的对象放入任何给定的集合中。

在这一行中,我需要将它强制转换为int类型吗:printf("value: %d", (int *)(f->value)); - Pooch
@Pooch:也许吧——恐怕我没有追踪完所有200行(或其他)的代码以确保。另一方面,你评论中的代码片段明显有问题——你将f->value强制转换为int *,但是然后将其传递给带有"%d"转换的printf,它期望一个int而不是指针。也许你想要的是类似于*(int *)(f->value)这样的东西? - Jerry Coffin

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