[C/C++] sizeof struct

Résolu/Fermé
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 - 7 sept. 2011 à 19:34
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 - 8 sept. 2011 à 08:38
Bonjour,

Je viens de remarquer quelques choses qui me surprend, mais peut-être pourra-t-on m'expliquer.
Je pensais que la sizeof d'un struct était égal à la somme des sizeof des champs de la struct.

Voici ce que j'obtient (en commentaire le résultat de sizeof)

char // 1
int  // 4

struct s1 { char c; }; // 1
struct s2 { int n; };  // 4
struct s3 { int n; char c; }; // 8 !!!

Comment se fait-il que l'on ait 1+4=8, et non pas 5 ?

2 réponses

supernico Messages postés 513 Date d'inscription dimanche 30 décembre 2007 Statut Membre Dernière intervention 20 novembre 2011 193
7 sept. 2011 à 19:47
Je ne suis pas sûr mais je pense que la structure a été paddée jusqu'à obtenir un multiple de 4.

Tu as essayé avec une structure contenant 1 int + 2,3 ou 4 char pour voir la valeur de sizeof ?
1
supernico Messages postés 513 Date d'inscription dimanche 30 décembre 2007 Statut Membre Dernière intervention 20 novembre 2011 193
7 sept. 2011 à 19:55
Tu devrais trouver chaque fois 8 car la structure est paddée afin de garder l'alignement de la mémoire sur des blocs continus
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
7 sept. 2011 à 20:00
En effet : 1 int et 1,2,3 ou 4 char => 8 / 1 int et 5,6,7 ou 8 char => 12
Cependant, il est possible d'avoir des valeurs intermédiaires, avec 5 char par exemple on a bien 5... alors je ne comprends pas pourquoi parfois c'est exact, et parfois non.
0
supernico Messages postés 513 Date d'inscription dimanche 30 décembre 2007 Statut Membre Dernière intervention 20 novembre 2011 193
7 sept. 2011 à 20:07
en fait si tu mets uniquement des char ça doit rester exactement ce que tu as demandé (5 char : sizeof = 5)
par contre dès qu'il y a des int dans la structure c'est paddé.
Le but est surtout de garder l'alignement mémoire pour que les int pointent sur des blocs mémoire de 32 bits continus

Par exemple il est déconseillé de faire ça :
struct s1 {
int a;
char b,c;
int d;
};

car tu pourrais avoir des problèmes avec le dernier int (sauf si ton compilateur est intelligent, auquel cas il allouera 12 octets au lieu de 10 comme prévu.

Il vaut mieux directement faire ça :
struct s1 {
int a;
char b,c;
char e,f; // inutilisés mais servent à padder
int d;
};

ou ça :
struct s1 {
int a;
int d;
char b,c;
};
0
KX Messages postés 16733 Date d'inscription samedi 31 mai 2008 Statut Modérateur Dernière intervention 31 janvier 2024 3 015
7 sept. 2011 à 20:22
En effet, je viens de regarder. Et l'alternance int, char, int char par exemple donne 16...
Sur un exemple simple comme ça, c'est facile à "optimiser", mais si ils sont imbriqués comme ceci
struct s1 { int a; char b; }; et struct s2 { struct s1 x,y; }; ce qui revient au même, l'optimisation est nettement moins évidente, et ça commence à faire pas mal de perte de mémoire !

Bon on va dire que le problème est résolu ;-)
0
supernico Messages postés 513 Date d'inscription dimanche 30 décembre 2007 Statut Membre Dernière intervention 20 novembre 2011 193
7 sept. 2011 à 20:25
oui on peut vite perdre pas mal de mémoire en imbriquant les structures ;)

la meilleure façon pour perdre un minimum de mémoire est de regrouper les int en début de chaque structure (ou tous les gros blocs qui ont besoin de 4 octets en général) puis les short (2 octets) puis les char (1 octet, les miettes ^^)
0
Char Snipeur Messages postés 9696 Date d'inscription vendredi 23 avril 2004 Statut Contributeur Dernière intervention 3 octobre 2023 1 297
8 sept. 2011 à 08:38
Bonjour,
juste pour ajouter ma petite touche, pour avoir eu des problèmes avec les alignements (C++ + fortran77).
En effet, le compilateur se réserve le droit d'aligner comme il le souhaite les variables dans une structure. Cet alignement est propre au compilateur et à son implémentation. Même s'il se dégage une méthode générale (alignement à 8), tout comme le byte groupe 8 octet : ce n'est pas une obligation.
Dans gcc il existe des commandes pour maitriser l'alignement des structure avec __atribute__ http://gcc.gnu.org/onlinedocs/gcc/Variable-Attributes.html#Variable-Attributes
Comme l'a dit supernico, au travail, nous mettons dans nos structures les plus gros éléments en premier et les plus petits en dernier. Cette simple méthode permet d'éviter en grande partie les problèmes d'alignements.
0