Alignement mémoire.

Bien organiser ses structures.

Voir version :

Pas de dépendances

Télécharger :

#include <stdio.h>

//#pragma pack(push, 1)

struct test
{
    char a;
    char c;
    int b;
};

struct test2
{
    char a;
    int b;
    char c;
};

int main()
{
    printf("sizeof test = %d\n",sizeof(struct test));
    printf("sizeof test2 = %d\n",sizeof(struct test2));
    return 0;
}




Commentaires


Voici un exemple de programme plus ou moins étrange non ?

* d'un compilateur a l'autre, il se peut (pas sur du tout, faut voir) que les résultats soient différents.
Si tel est le cas, merci de me mailer !! (précisez le nom du compilateur et le systeme utilisé !) fvirtman@yahoo.fr
Merci !

Voici ce que j'obtiens :
sizeof(test)=8
sizeof(test2)=12


Alors dilemne : pourquoi les tailles sont elles différentes, alors que finalement, les 2 structures contiennet 2 char et un int.
Et pire que ça, pourquoi 8 ou 12, alors que :
sizeof(char) = 1
sizeof(int) = 4
En toute logique on devrait avoir 6 aux 2 cas non ?


Mais la raison de ces chiffres vient carrément de la façon meme de fonctionner de votre processeur.
(c'est juste par curiosité, vous n'avez pas a vous soucier de cela dans la programmation de tous les jours...)
On parle d'alignement mémoire.

Les processeurs 32 bits sont optimisés pour récupérer des données 32 bits, c'est a dire 4 octets.
Pour etre efficace, une variable sur 4 octets DOIT etre alignée a une adresse qui se divise par 4.

Ainsi, n'importe quel int verra son début aligné sur une adress qui se divise par 4.
Il en va de meme pour les structures.

Ainsi, si l'on représente la mémoire ainsi :

0  1  2  3  4  5  6  7  8  9  10 11 12
|--|--|--|--|--|--|--|--|--|--|--|--|

et un int ainsi : 

[-----------]
et un char ainsi :

[--]

Alors en mémoire, voici les possibilités :

0  1  2  3  4  5  6  7  8  9  10 11 12
|--|--|--|--|--|--|--|--|--|--|--|--|
[-----------] <-- autorisé
   [-----------] <-- NON autorisé
      [-----------] <-- NON autorisé      
         [-----------] <-- autorisé
[--] <-- autorisé
   [--] <-- autorisé
      [--]   <-- autorisé

Et voici comment sont faites les structures en mémoire :

test :

0  1  2  3  4  5  6  7  8  9  10 11 12
|--|--|--|--|--|--|--|--|--|--|--|--|
[--]--]*****[-----------]
2 char  ^      un int.
Perte 2 octets

test2 :

0  1  2  3  4  5  6  7  8  9  10 11 12
|--|--|--|--|--|--|--|--|--|--|--|--|
[--]********[-----------[--]
1 char  ^      un int.    1 char
Perte 3 octets



On peut alors se demander pourquoi sizeof(test2) = 12 et non 9.
Car souvent, on préfere finir par un multiple de 4 également pour la prochaine variable...
Ce qui n'est pas forcément vrai si on fait une structure de 3 char, ou il acceptera de nous dire que sizeof = 3...
Apres, il y a aussi la petite touche du compilateur...
C'est pour ça que si vous trouvez des résultats différents pour d'autres compilos/OS, merci de me tenir au courant ! :)

Note additionnelle : un double sera aligné sur un multiple de 8 octets
un short sur un multiple de 2 octets
un char n'importe ou...


Conclusion :
Ce genre de trucs ne perturbe pas le programmeur occasionnel.
Il peut etre genant si vous voulez optimiser de la mémoire : sachez ranger correctement vos structures !
Mettez d'abord les int, et a la fin les char...


-------------- DESACTIVER L'ALIGNEMENT MEMOIRE ----------
(thx to Althar93)

Activez la ligne dans le code :

#pragma pack(push, 1)

Cette pragma permet de forcer les octets a s'aligner sur un pas d'un seul octet (le 1) : donc que les données soient contiguees sans pertes d'octets.

explications plus détaillées
http://publib.boulder.ibm.com/infocenter/comphelp/v9v111/index.jsp?topic=/com.ibm.xlcpp9.aix.doc/compiler_ref/pragma_pack.htm