【问题标题】:C Dereference void* pointerC 取消引用 void* 指针
【发布时间】:2011-06-17 23:11:34
【问题描述】:

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

我希望我的队列能够保存任何类型的对象,因此我创建了一个 QueueElement 结构来保存指向任何类型对象的 void 指针。我认为一切正常,除了我无法从我的 QueueElement 结构中读取“位置”和“值”字段。尝试编译时出现以下错误。

错误:

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

我很确定我只是没有正确投射。任何帮助表示赞赏。

再次感谢, 狗

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;
}

【问题讨论】:

    标签: c pointers void void-pointers


    【解决方案1】:

    QueueElementStruct 的定义必须在 Runnable.c 中可见才能访问它的字段。您可以将QueueElementStruct 放入可以包含在Runnable.cQueueElement.c 中的标头中。或者,您可以使用 GetPosition 函数并添加 GetValue 函数并使用来自 Runnable.c 的函数,而不是直接访问字段。

    【讨论】:

    • Runnable.c 包含 Queue.h,而 Queue.h 又包含 QueueElement.h 包含的链接是否有效?
    • 确实如此,但 QueueElement.h 并没有说定义 QueueElementStruct 的成员,它只是暗示它的存在。如果我包含 QueueElement.h,我只知道有一个名为 QueueElementStruct 的结构,而不是它的组成部分。只有 QueueElement.c 知道 QueueElementStruct 的成员是什么。
    • Logan,我使用了您的建议以及 Jerry 的建议和我编译的代码。谢谢你们的帮助。
    【解决方案2】:

    在取消引用之前,您必须将 void * 重新指向“真实”类型。例如,如果您以int 开头,您可以获取其地址,并将其放入队列中。要查看int,您必须将其转换回int *。跟踪真实类型可能(通常是)非平凡的(例如,创建您希望能够放入集合中的所有类型的枚举并将其中一个与集合中的每个项目相关联)。

    C++(例如)选择只将一种类型的对象放入任何给定的集合是有原因的。

    【讨论】:

    • 不要在这一行将它转换回 int : printf("value: %d", (int *)(f->value));
    • @Pooch:也许——恐怕我没有跟踪所有 200 行(或其他)代码来确定。 OTOH,您评论中的那段代码显然有问题——您将f-&gt;value 转换为int *,然后通过"%d" 转换将其传递给printf,它需要int,而不是一个指针。也许您打算像*(int *)(f-&gt;value) 这样的东西?
    猜你喜欢
    • 2012-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多