2011-01-30 39 views
5

Hey ragazzi, sono nuovo di C e per il mio primo progetto ho bisogno di implementare una coda basata su array. Voglio che la mia coda sia in grado di contenere qualsiasi tipo di oggetto, così ho creato una struttura QueueElement per contenere un puntatore vuoto a un oggetto di qualsiasi tipo. Penso che tutto funzioni, ma non riesco a leggere i campi "position" e "value" dalla mia struct QueueElement. Ottengo il seguente errore quando provo a compilare.C Dereference void * pointer

Errore:

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

Sono abbastanza sicuro che non sto solo lanciare correttamente. Qualsiasi aiuto è apprezzato.

Grazie ancora, 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; 
} 

risposta

6

La definizione di QueueElementStruct deve essere visibile in Runnable.c poter accedere ai campi di esso. È possibile inserire QueueElementStruct in un'intestazione che è possibile includere in Runnable.c e QueueElement.c. In alternativa, è possibile utilizzare la funzione GetPosition e aggiungere una funzione GetValue e utilizzare quelli da Runnable.c invece dell'accesso diretto al campo.

+0

Runnable.c include Queue.h che a sua volta include QueueElement.h Questo collegamento di include lavoro? – Pooch

+1

Lo fa, ma QueueElement.h non dice definire i membri di QueueElementStruct, suggerisce semplicemente la sua esistenza. Se includo QueueElement.h tutto quello che so è che esiste una struttura chiamata QueueElementStruct, non i suoi componenti. Solo QueueElement.c sa quali sono i membri di QueueElementStruct. –

+0

Logan, ho usato il tuo consiglio insieme a Jerry's e il mio codice compilato. Grazie per l'aiuto ragazzi. – Pooch

4

È necessario eseguire il cast dello void * per puntare al tipo "reale" prima di poterlo ritrasmettere. ad esempio, se inizi con uno int, puoi prendere il suo indirizzo e metterlo in coda. Per guardare lo int, devi ricondurlo a int *. Tenere traccia del tipo reale può essere (di solito è) non banale (ad esempio, creando un'enumerazione di tutti i tipi che si desidera essere in grado di inserire nella raccolta e associare uno di quelli con ciascun elemento della raccolta).

C'è un motivo per cui il C++ (per un esempio) sceglie solo un tipo di oggetto in una determinata raccolta.

+0

non lo rigirò in un int su questa riga: printf ("valore:% d", (int *) (f-> valore)); – Pooch

+0

@Pooch: Forse - Temo di non aver tracciato tutte le 200 (o qualsiasi altra) riga di codice per essere sicuro.OTOH, il bit di codice nel tuo commento ha chiaramente un problema: stai trasmettendo 'f-> value' a' int * ', ma poi lo passi a' printf' con una conversione ''% d "', che si aspetta un 'int', non un puntatore. Forse intendevi qualcosa come '* (int *) (f-> valore)'? –

+0

Grazie Jerry, la tua espressione del cast ha funzionato! – Pooch