[Astuce]Warning pour minimiser le padding
Bonsoir ^_^,
Je ne savais pas où mettre ce message, j'ai hésité avec la rubrique "Contribuez", mais ce n'est pas vraiment de moi =). J'ai trouvé cette astuce sur un blog et je vous la partage car je la trouve très utile. Par contre, elle ne fonctionne que sous Visual.
Vous n'êtes sûrement pas sans savoir que, afin de minimiser l'espace mémoire, les variables membres d'une classe ou d'une structure doivent être organisées suivant un ordre précis afin d'éviter de créer des "paddings" inutiles. J'imagine que le compilateur est suffisamment intelligent pour pouvoir réorganiser lui-même les variables (quelqu'un pourrait confirmer ou infirmer ?), mais c'est toujours mieux de le faire soi-même.
Concrètement, voici une structure qui illustre ce soucis :
Code:
1 2 3 4 5 6 7
| struct Test
{
char a; // 1 octet
int b; // 4 octets
char c; // 1 octet
int d; // 4 octets
}; |
Puisque l'alignement se fait sur 4 octets, le compilateur va donc automatiquement ajouter un padding de 3 octets entre la variable a et b, et 3 autres entre c et d, ce qui donnera en fait ceci :
Code:
1 2 3 4 5 6 7 8 9
| struct Test
{
char a; // 1 octet
char pad[3]; // 3 octets
int b; // 4 octets
char c; // 1 octet
char pad2[3]; // 3 octets
int d; // 3 octets
}; |
On a donc, dans cette structure, 6 octets qui sont gâchés. Il est parfois assez chiant de devoir compter soi-même pour réorganiser les données, et en fait, il existe un warning à activer qui permet de lever un warning automatiquement pour indiquer ça. C'est bizarre car même avec le warning niveau 4 il n'est pas activé.
L'astuce consiste en encadrer la structure par #pragma warning(error: 4820) et #pragma warning(disable: 4820), ce qui donne :
Code:
1 2 3 4 5 6 7 8 9
| #pragma warning(error: 4820)
struct Test
{
char a; // 1 octet
int b; // 4 octets
char c; // 1 octet
int d; // 4 octets
};
#pragma warning(disable: 4820) |
Et le compilateur lève le warning suivant :
'Test' : '3' bytes padding added after data member 'Test::a'
'Test' : '3' bytes padding added after data member 'Test::c'
On sait donc immédiatement ou le padding est ajouté, et on peut donc réorganiser la structure comme ceci :
Code:
1 2 3 4 5 6 7 8
| struct Test
{
int b; // 4 octets
int d; // 4 octets
char a; // 1 octet
char c; // 1 octet
char pad[2]; // 2 octets
}; |
Et hop ! Au lieu de perdre 6 octets sur la structure on n'en perd que deux =). Je sais très bien que c'est le genre de micro-optimisation qui ne va pas changer grand chose en terme de performances, mais c'est tellement simple à réorganiser que je vois pas pourquoi on s'en priverait ;) On peut ensuite enlever les #pragma et aller tester une autre classe.