2010-01-26 1 views
0

Je veux 'construire' (lire: malloc et memset) ma hashtable dans c. Pour ce faire, j'ai créé une fonction comme suit:Puis-je désigner un «constructeur» de type Java dans c?

int maketable(struct hash_entry **table, int size){ 

    table = (struct hash_entry **)malloc(size*sizeof(struct hash_entry *)); 
    int i = 0; 
    for (; i<size; i++) { 
     memset(table[i], '\0', sizeof(struct hash_entry *)); 
    } 
    return 0; 

} 

Étant donné que la table aura été déclarée comme

struct hash_entry **table[size] 

avant d'entrer dans ce code, je ne perdrai rien quand je reviens de MakeTable, droite?

EDIT: passe-t-table en maketable() assurer que tant que je change les données table points, les changements seront conservés?

EDIT II: Je tente d'allouer un tableau de pointeurs sur des pointeurs vers hash_entries

+1

Je ne comprends pas. Vous allouez de la mémoire sur la pile pour la variable, puis réallouez quelque chose dans la fonction? - En outre, 'table' est une variable locale. Vous allouer quelque chose et l'affecter à 'table' qui disparaîtra lorsque la fonction revient, provoquant une fuite de mémoire. –

+0

Le problème est que je ne comprends pas non plus. Est-ce que ma déclaration de struct hash_entry ** table [taille] alloue implicitement la mémoire pour moi? Dans ce cas, je dois encore malloc pour les hash_entrys eux-mêmes quand je les déclare, non? –

+1

La déclaration alloue de la mémoire pour un tableau avec la taille 'size' de pointeurs vers des pointeurs de type' hash_entry' sur la pile. Il n'alloue pas de mémoire pour les emplacements vers lesquels les éléments du tableau vont pointer. –

Répondre

4

Votre code affecte à la variable locale table, l'appelant n'est pas affecté. Cela entraîne une fuite de mémoire.

En dehors de la fonction, vous avez déclaré table sous la forme d'un tableau de pointeur sur les pointeurs de struct hash_entry - Je suppose que vous préférez simplement un tableau de pointeurs pour structuer les entrées de hachage.

Si vous déclarez table en tant que groupe, il n'est pas nécessaire de le faire. Vous avez juste besoin d'une boucle pour définir chaque élément à NULL (Ne pas memset chaque élément à zéro).

Si l'objectif est d'affecter toute la table, c'est perhps ce que vous cherchez:

struct hash_entry **table; 
... 
int maketable(struct hash_entry ***table, int size){ 

    *table = malloc(size* sizeof **table); 
    int i = 0; 
    for (; i<size; i++) { 
     (*table)[i] = NULL; 
    } 
    return 0; 
} 

appel comme

maketable(&table,100); 

Je préfère faire que retourner la table comme ceci:

struct hash_entry ** maketable(int size){ 
    return calloc(size, sizeof(struct hash_entry *)); 
} 

si la déclaration est struct hash_entry **table[size] vraiment ce que vous voulez, vous devez dire nous ce que votre fonction maketable() est censée faire (par ex. voulez-vous un 'tableau' dynamiquement alloué comme l'un des éléments de cette table?

2

Vous devez affecter le résultat de malloc-* table - sinon il ne sera pas visible en dehors de la fonction.

De même, la manière typique d'utiliser ceci est de déclarer un pointeur vers la hashtable et de passer l'adresse de ce pointeur dans la fonction.

+0

comment je fais ça? –

+1

'* table = (struct hash_entry *) malloc ...' –

1

Non. Vos types ne correspondent pas.

Essayez-vous d'allouer une table d'entrées de hachage (à savoir le type de table[i] est struct hash_entry), une table de pointeurs à hash_entries (à savoir le type de table[i] est struct hash_entry *), ou autre chose? Basé sur la lecture de votre code, je suppose le premier cas, mais laissez-moi savoir si c'est faux.

En supposant que vous allouer dynamiquement une table de struct hash_entry, votre déclaration de la table dans l'appelant doit être

struct hash_entry *table; // 1 *, no array dimension 

la fonction doit être appelée comme

int result = maketable(&table, number_of_elements); 

et défini as

int maketable (struct hash_entry **table, size_t size) 
{ 
    int r = 0; 

    // sizeof **table == sizeof (struct hash_entry) 
    *table = malloc(sizeof **table * size); 
    // *ALWAYS* check the result of malloc() 
    if (*table) 
    { 
    size_t i; 
    for (i = 0; i < size; i++) 
     memset(&(*table)[i], 0, sizeof (*table)[i]); 
    r = 1; 
    } 
    return r; 
} 

Un couple de choses à signaler. Tout d'abord, ne pas diffuser le résultat de malloc(). A partir de C89, vous n'avez pas besoin de le faire, et la distribution supprimera un diagnostic si vous oubliez d'inclure stdlib.h ou si vous n'avez pas de prototype pour malloc() dans la portée. Deuxièmement, vous pouvez utiliser l'opérateur sizeof sur les objets au lieu des types. Cela peut aider à réduire certains maux de tête de maintenance (c'est-à-dire, si vous modifiez le type de table dans la liste de paramètres, vous n'avez pas besoin de modifier les appels sizeof en même temps).

Enfin, notez que l'adresse de la table est en cours de transmission à la fonction; puisque nous essayons d'écrire sur une valeur de pointeur, nous devons passer un pointeur vers ce pointeur.

Si vous essayez de créer une table de pointeurs vers struct hash_entry, le code est essentiellement le même, juste un niveau supplémentaire d'indirection:

votre déclaration de la table dans l'appelant doit être

struct hash_entry **table; // 2 *, no array dimension 

la fonction doit être appelée comme

int result = maketable(&table, number_of_elements); 

et défini comme

int maketable (struct hash_entry ***table, size_t size) 
{ 
    int r = 0; 

    // sizeof **table == sizeof (struct hash_entry *) 
    *table = malloc(sizeof **table * size); 
    // *ALWAYS* check the result of malloc() 
    if (*table) 
    { 
    size_t i; 
    for (i = 0; i < size; i++) 
     (*table)[i] = NULL; 
    r = 1; 
    } 
    return r; 
} 

EDIT Il y avait un bug dans les maketable exemples; table doit être déréférencé avant d'appliquer l'indice, c'est-à-dire (*table)[i]. Nous appliquons l'indice à ce que tablepointe à, pas le pointeur de table lui-même.

Désolé pour toute confusion.

+0

J'essaye d'allouer une table de pointeurs aux pointeurs à hash_entries. –

+0

Ensuite, vous devez déclarer la table comme 'struct hash_entry *** table;'. Le type du paramètre dans la fonction doit être 'struct hash_entry **** table'. Tout le reste devrait être le même que le deuxième exemple. –

Questions connexes