C разыменование void * указатель - PullRequest
5 голосов
/ 30 января 2011

Эй, ребята, я новичок в C, и для моего первого проекта мне нужно реализовать очередь на основе массива. Я хочу, чтобы моя очередь могла содержать любые объекты, поэтому я создал структуру QueueElement для хранения пустого указателя на объект любого типа. Я думаю, что все работает, за исключением того, что я не могу прочитать поля 'position' и 'value' из моей структуры 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;
}

Ответы [ 2 ]

6 голосов
/ 30 января 2011

Определение QueueElementStruct должно быть видно в Runnable.c, чтобы иметь возможность доступа к его полям. Вы можете поместить QueueElementStruct в заголовок, который вы можете включить в Runnable.c и QueueElement.c. Кроме того, вы можете использовать функцию GetPosition, добавить функцию GetValue и использовать ее из Runnable.c вместо прямого доступа к полю.

4 голосов
/ 30 января 2011

Вы должны привести void * обратно к точке «реального» типа, прежде чем сможете разыменовать его.Например, если вы начинаете с int, вы можете взять его адрес и поместить его в очередь.Чтобы посмотреть на int, вам придется вернуть его к int *.Отслеживание реального типа может быть (как правило, является нетривиальным) (например, создание списка всех типов, которые вы хотите иметь возможность поместить в коллекцию, и ассоциирование одного из них с каждым элементом в коллекции).

Существует причина, по которой C ++ (для одного примера) предпочитает помещать только один тип объекта в любую заданную коллекцию.

...