2010-12-07 32 views
2

je la structure de données suivante dans C:problème lors de la coulée en C

typedef struct { 
    void* buffer; 
     ... 
} SharedMemory; 

J'ai défini un sharedMemoryBuffer qui contiendra un tableau de SharedMemory struct:

sharedMemoryBuffer = createSharedMemory("/xxxyz", NUM_BLOCKS * sizeof(Block)); 

mon problème est maintenant essayer de lire dans la mémoire partagée un bloc dans une position donnée. Je pensais que ce qui suit devrait être suffisant, mais le compilateur C est plaignais:

Block* block = (Block*)sharedMemoryBuffer->buffer[readPosition]; 

L'erreur est:

Invalid use of void expression. 

Comment dois-je jeter la dernière ligne de code tel que le compilateur ne crie pas à moi à propos de cette ligne?

Merci

+1

Basé sur les lignes que vous avez fournies, cela ressemble à 'void * buffer;' devrait être réellement 'Block * buffer;' ici. – asveikau

+0

Oui, il devrait. Le problème est que j'ai conçu cette structure pour qu'elle puisse être utilisée dans d'autres situations. Existe-t-il un autre moyen de coder en C de sorte que je puisse utiliser ma structure SharedMemory avec plusieurs types? char *, int *, etc? Quelque chose comme des génériques en C#? –

+0

Pas vraiment. C'est assez bon pour la plupart des situations. Si vous aviez du C++, vous pourriez utiliser des modèles mais je ne veux pas être le type "Si vous aviez C++, vous pourriez ...". C'est assez bon pour la plupart des programmeurs C compétents. –

Répondre

4

sharedMemoryBuffer->buffer est de type void *. Cela signifie que vous ne savez pas de quel type il s'agit, vous ne pouvez donc pas le déréférencer (avec * ou []).

Si c'est en fait la buffer que vous voulez lancer, vous devriez regarder dans:

Block* block = ((Block*)(sharedMemoryBuffer->buffer))[readPosition]; 

ou, plus probable:

Block* block = &(((Block*)(sharedMemoryBuffer->buffer))[readPosition]); 

puisque vous essayez d'obtenir un pointeur à l'élément de tableau désiré.

+0

Hmm. Je reçois maintenant un "types incompatibles lors de l'initialisation de type 'struct Block *' en utilisant l'erreur de type 'Block' –

+0

Non, le code OP est équivalent à '(Block *) (sharedMemo ryBuffer-> buffer [readPosition]) 'parce que' -> 'et' [] 'lient tous deux le tigter. –

+0

@devoured, c'est parce que l'indexation d'un pointeur X vous donne un 'X'. Si vous voulez un pointeur vers l'élément indexé par 'readPosition', voir ma mise à jour. – paxdiablo

2

Le tampon est un pointeur vide. Vous ne pouvez pas indexer dans un pointeur vide.

Le caractère non signé peut fonctionner mieux car il est défini comme un octet unique.

+0

Mais il devra ensuite indexer manuellement par 'sizeof (Block)'. Mieux vaut lancer le buffer à 'Block *', _then_ l'indexer. En outre, il est toujours préférable d'utiliser 'void *' lorsque les données non typées sont appelées. 'unsigned char *' pour le stockage aléatoire n'est pas intuitif. –

4

Le problème est la priorité des opérateurs ici: l'opérateur d'index ([]) a une priorité plus élevée que la distribution, il essaie donc de prendre l'indice d'un void * et de le jeter à un Block * plutôt que la coulée du void * à un Block * et puis l'indexer. Utilisez des parenthèses:

Block *block = &((Block *)sharedMemoryBuffer->buffer)[readPosition]; 

ou (la façon dont je préfère avec l'arithmétique de pointeur):

Block *block = (Block *)sharedMemoryBuffer->buffer + readPosition; 

ou, si vous voulez copier le Block à une variable de la pile pour une raison quelconque:

Block block = ((Block *)sharedMemoryBuffer->buffer)[readPosition]; 

EDIT: correction d'une erreur. Mon code a produit un Block au lieu d'un Block * comme OP nécessaire.

+0

J'ai pensé à la paranthésis et essayé de toutes les façons possibles. Il semble que c'était de toutes les manières possibles, mais celle que vous avez montrée :( –

+0

Mais maintenant que j'y pense, je ne comprends pas. Je ne devrais pas d'abord essayer de "trouver" l'objet dans le tableau et seulement –

+0

@devoured - Non. Vous ne pouvez pas indexer un pointeur 'void *', vous devez d'abord le lancer vers le type d'élément, c'est-à-dire un tableau de 'Block's ou un tableau de pointeurs vers' –

1

Vous ne pouvez pas déférer un pointeur vide. Vous devez lancer un pointeur vide sur char * puis ajouter une position de lecture, puis renvoyer vers Bloc *.

2

permet le briser par parenthèse comme le compilateur voit

Block* block = (Block*)(sharedMemoryBuffer->buffer[readPosition]); 

Vous remarquerez là que vous casting pour bloquer * après avoir utilisé les indices de déréférencer un pointeur vide qui signifie que vous essayez de jeter un void-Block*

Qu'est-ce que vous voulez sans doute faire est:

Block* block = ((Block*)(sharedMemoryBuffer->buffer))+readPosition; 

qui vous pointera sur le readPosition Bloc dans le tampon