Re: [gull] Subtilité de C n° 2 : type de retour de malloc

Marc Mongenet marc at mongenet.ch
Thu Apr 3 18:42:48 CEST 2008


Le 03/04/08, Daniel Cordey<dc at mjt.ch> a écrit :
>  > >  Ainsi, je peux m'affranchir de l'aproxinmation de sizeof() sur les
>  > > structure. Et non... sizeof ne calcul pas le padding a la fin de la
>  > > structure... !
>  >
>  > Ben si.
>
> Je viens de voir que ISO C le defini comme tu le dis. Mais ce n'etait
> absolument pas le cas au debut et jusqu'a cette version d'ISO. Ce changement
> pose probleme car il modifie le comportement de tous les compilateurs
> precedents cette adoption. C'est la raison pour laquelle j'avais cette macro
> qui me garantissait que la valeur retournee etait la meme, quelque soit
> l'architecture, l"OS ou le compilateur.
>

Pas seulement ISO C. Le bouquin K&R revu pour ANSI C89 (donc
bientôt 20 ans) dit que sizeof donne une valeur utilisable pour
mettre la structure dans une table. Or il faut tenir compte du padding
final pour mettre la structure dans une table. En plus, il ne dit rien
d'un changement de comportement de sizeof, alors qu'un appendice
complet est consacré aux changements K&R C -> ANSI C, et consacre
notamment un paragraphe à un détail comme le type de la valeur
donnée par sizeof (d'abord int, puis unsigned dans certaine compilateurs,
et finalement size_t dans ANSI C).

En plus, un sizeof ne comptant pas le padding final serait
pratiquement inutilisable comme le montre ces deux exemples.

Exemple 1 :
struct s *tab;
/* Pour allouer une table de N struct s comme suit, on a
   impérativement besoin d'un sizeof comptant tous les paddings,
   sinon on n'alloue pas assez de RAM ! */
tab = malloc(N * sizeof(struct s));

Exemple 2 :
struct s tab[N];
size_t i;
for (i = 0; i < sizeof tab / sizeof tab[0]; ++i) {
/* Pour itérer sur toute la table, on a impérativement besoin
   d'un sizeof comptant tous les paddings, sinon on risque
   d'itérer trop loin ! */
}

Cela dit, avec un sizeof inutilisable sur les structures, les
compilateurs auraient pu changer de comportement sans
déranger beaucoup de programmes. :-)

>  > char *p1, *p2 = malloc(1);
>  > unsigned long address = (unsigned long)p2;
>  > p1 = (char*)address;
>  > /* Le standard assure-t-il que p1==p2? Je n'en suis pas sûr. */
>
> Oui, sans aucun doute. Toutefois... il ne faut pas sortir du cadre de
>  l'assignation pour que cela fonctionne, car :
>
>  p2++ est different de adress++. Mais ca, nous le savons deja :-)

Tout à fait.

-- 
Marc Mongenet
Creator of the Web 2 Markup Language
http://w2ml.com



More information about the gull mailing list