53 votes

Pourquoi est-il plus sûr d'utiliser sizeof(*pointeur) dans malloc

Étant donné que

struct node
{
     int a;
     struct node * next;
};

Pour malloquer une nouvelle structure,

struct node *p = malloc(sizeof(*p));

est plus sûr que

struct node *p = malloc(sizeof(struct node));

Pourquoi ? Je pensais que c'était la même chose.

77voto

AndreyT Points 139512

C'est plus sûr parce que vous n'avez pas à mentionner le nom du type deux fois et que vous n'avez pas à construire l'orthographe correcte pour la version "déréférencée" du type. Par exemple, vous n'avez pas à "compter les étoiles" en

int *****p = malloc(100 * sizeof *p);

Comparez cela à la méthode basée sur les types sizeof sur

int *****p = malloc(100 * sizeof(int ****));

où vous devez vous assurer que vous avez utilisé le bon nombre de * sous sizeof .

Pour passer à un autre type, il suffit de changer un seul endroit (la déclaration de l'option p ) au lieu de deux. Et les personnes qui ont l'habitude de jeter le résultat de malloc doivent changer trois places.

De manière plus générale, il est très judicieux de respecter la directive suivante : les noms de types doivent figurer dans les déclarations et nulle part ailleurs. Les déclarations proprement dites doivent être indépendantes des types. Elles doivent éviter autant que possible de mentionner des noms de types ou d'utiliser d'autres caractéristiques spécifiques aux types.

Cette dernière signifie : Évitez les moulages inutiles. Évitez la syntaxe inutile des constantes spécifiques au type (comme 0.0 ou 0L où un simple 0 suffirait). Évitez de mentionner les noms de type sous sizeof . Et ainsi de suite.

22voto

Alok Save Points 115848

Parce que si à un moment ultérieur dans le temps p doit pointer vers un autre type de structure, alors votre déclaration d'allocation de mémoire à l'aide de la fonction malloc n'a pas à changer, il alloue toujours suffisamment de mémoire pour la nouvelle version de l'application. type . Il assure :

  • Il n'est pas nécessaire de modifier l'instruction d'allocation de mémoire chaque fois que vous changez le nom de l'utilisateur. type pour lequel il alloue de la mémoire.
  • Votre code est plus robuste et moins sujet aux erreurs manuelles.

En général, c'est toujours une bonne pratique de ne pas s'appuyer sur des types concrets et la première forme le fait, sans coder en dur un type.

7voto

ruben2020 Points 802

C'est pratique, car vous pouvez le convertir :

struct node *p= malloc(sizeof(*p));

Dans ça :

#define MALLOC(ptr)   (ptr) = malloc(sizeof(*(ptr) ))

struct node *p;
MALLOC(p);

Ou, pour un tableau :

#define MALLOC_ARR(ptr, arrsize) \
       (ptr) = malloc(sizeof(*(ptr) ) * arrsize)

struct node *p;
MALLOC_ARR(p, 20);

Et pourquoi est-ce sûr ? Parce que l'utilisateur qui utilise ces macros est moins susceptible de commettre les erreurs décrites par AndreyT, tout comme dans le cas de DIM() pour obtenir la taille d'un tableau statique.

#define DIM(arr)   ((sizeof(arr))/(sizeof(arr[0])))

C'est également plus sûr, car l'utilisateur n'a pas besoin de rendre la taille du tableau statique cohérente à plusieurs endroits. Définissez la taille du tableau à un seul endroit, puis utilisez simplement la fonction DIM() et le tour est joué ! Le compilateur s'en occupe pour vous.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X