2011-01-30 8 views
5

Hé les gars, je suis nouveau en C et pour mon premier projet j'ai besoin d'implémenter une file d'attente basée sur un tableau. Je souhaite que ma file d'attente puisse contenir n'importe quel type d'objet. J'ai donc créé une structure QueueElement pour contenir un pointeur vide vers un objet de n'importe quel type. Je pense que tout fonctionne, sauf que je suis incapable de lire les champs 'position' et 'value' de ma structure QueueElement. Je reçois l'erreur suivante lorsque j'essaie de compiler.C Déréférence void * pointer

Erreur:

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

Je suis sûr que je ne suis pas coulée correctement. Toute aide est appréciée.

Merci encore, 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; 
} 

Répondre

6

La définition de QueueElementStruct doit être visible dans Runnable.c pour pouvoir accéder aux champs de celui-ci. Vous pouvez mettre QueueElementStruct dans un en-tête que vous pouvez inclure dans Runnable.c et QueueElement.c. Vous pouvez également utiliser votre fonction GetPosition et ajouter une fonction GetValue et utiliser celles de Runnable.c au lieu d'un accès direct aux champs.

+0

Runnable.c inclut Queue.h qui inclut à son tour QueueElement.h Cette liaison de includes fonctionne-t-elle? – Pooch

+1

Il le fait, mais QueueElement.h ne dit pas définir les membres de QueueElementStruct, il suggère simplement son existence. Si j'inclue QueueElement.h tout ce que je sais c'est qu'il y a une structure nommée QueueElementStruct, pas ses constituants. Seul QueueElement.c sait ce que sont les membres de QueueElementStruct. –

+0

Logan, j'ai utilisé tes conseils avec Jerry's et mon code compilé. Merci pour l'aide les gars. – Pooch

4

Vous devez retourner le void * pour pointer sur le type "réel" avant de pouvoir le déréférencer. par exemple, si vous commencez par int, vous pouvez prendre son adresse et la mettre dans la file d'attente. Pour regarder le int, vous devrez le renvoyer à int *. Le suivi du type réel peut être (généralement) non trivial (par exemple, créer une énumération de tous les types que vous voulez pouvoir mettre dans la collection et en associer un à chaque élément de la collection).

Il y a une raison pour laquelle C++ (par exemple) opte pour ne placer qu'un type d'objet dans une collection donnée.

+0

ne pas le renvoyer dans un int sur cette ligne: printf ("value:% d", (int *) (f-> valeur)); – Pooch

+0

@Pooch: Peut-être - je crains de ne pas avoir retracé les 200 lignes de code (ou peu importe) pour être sûr.OTOH, le bit de code dans votre commentaire a clairement un problème - vous lancez 'f-> valeur' à' int * ', mais en le passant à' printf' avec une conversion '"% d "', qui attend un 'int', pas un pointeur. Peut-être que vous vouliez quelque chose comme '* (int *) (f-> value)'? –

+0

Merci Jerry, votre expression de casting a fonctionné! – Pooch