2011-03-31 3 views
2

Je vous écris un tableau dynamique en C.programmation générique en C Question

typedef struct __c_array { 
    void**_elem; 
    int cur_size; 
    int capacity; 
}c_array; 

Mon interface ressemble à ceci:

extern void push_back_c_array (c_array*, void *); 

Maintenant, l'utilisateur devra allouer de la mémoire pour l'élément à être poussé dans le tableau. Est-il possible d'éviter cela en utilisant void *.

Je veux l'utiliser pour faire suite

int a = 5; 
push_back_c_array (<ARRAY_PTR>, a); 

Est-ce possible.

+0

Il est dangereux de typer la structure. Il a déjà un type; tout ce qui a été fait est de rendre le code plus complexe, en demandant au lecteur de se référer et de se souvenir du type sous-jacent du typedef. –

+0

Pourriez-vous s'il vous plaît expliquer? – Avinash

+7

Je ne suis pas d'accord avec «c'est dangereux pour typedef la structure», dans ce cas, la structure sera un handle opaque pour ses utilisateurs d'utiliser le tableau. – IanNorton

Répondre

2

Il est possible, si vous fournissez une version de push_back_c_array(), de copier la valeur fournie. Pour cela, vous aurez besoin d'un argument supplémentaire, qui spécifie la taille de la valeur:

push_back_c_array(c_array* arr, void* val, unsigned int size); 

Vous allouez de la mémoire en tas pour la nouvelle valeur, puis faire memcpy. Mais après cela, vous devrez le libérer. Donc, vous devrez vous rappeler, quelles valeurs sont allouées par vous, et lesquels - par l'appelant. Plutôt méchant ... Donc, si vous faites cela - faites-le toujours, et décrivez cette convention dans la documentation à votre fonction.

+0

Merci, mais ajouter un paramètre de taille sera un problème de perspective d'utilisation. – Avinash

+0

Pas du tout. C'est un cas courant pour beaucoup de fonctions C. (Prenez, par exemple, le même memcpy()). – weekens

+0

Pas de taille, pas de calloc! –

0

Votre tableau d'exemple contient des éléments de type (void *). Il contient des pointeurs. Vous semblez vouloir qu'il tienne des types arbitraires. Dans ce cas et int. Voulez-vous stocker des copies de données insérées ou simplement stocker les pointeurs qui vous sont donnés par l'appelant? Il y a quelque temps, je voulais un comportement de type tableau simple pour un jeu que j'écrivais et j'ai créé xrlist. Un peu plus tard, je voulais les stocker et les accéder au hasard, alors j'ai trouvé xrhash.

xrlist et pointeurs xrhash fourni par l'utilisateur de stocker et attendre tous les éléments à être du même type (xrhash a une hashcode et la fonction de rappel de comparaison)

0

Vous pourriez être mieux servis allouer une petite partie de la mémoire (peut-être tenir unions) au début, et repoussant les éléments jusqu'à ce que vous le remplissiez. Ensuite, soit realloc, ou allouer un tableau deux fois la taille et copiez tout.

0

exemple avec a = 5 devrait fonctionner aussi longtemps que vous utiliserez des entiers ou tout autre type qui a la même taille que int. L'utilisateur du tableau générique voudra pousser des structures, tout comme votre. Mais, les gros éléments ne peuvent/ne doivent pas être transmis par valeur, mais leur pointeur doit être passé.

en utilisant générique et ne pas être lié à sizeof (int) apporter un effort supplémentaire de l'utilisateur. Je pense que la meilleure solution est que vous passez le pointeur alloué (void *) dans la fonction et que celui qui veut sortir cet élément, devrait libérer() cette structure.

+0

Je suis d'accord avec vous pour les grandes structures, et de telles directives peuvent être publiées, mais pour les petits types de données comme ints, il est vraiment incommode de demander à l'utilisateur d'allouer chaque fois. – Avinash