J’ai un fond C #. Je suis très novice dans un langage de bas niveau comme C.
En C #, la mémoire de struct
est définie par défaut par le compilateur. Le compilateur peut réordonner les champs de données ou append des bits supplémentaires entre les champs de manière implicite. Donc, j’ai dû spécifier un atsortingbut spécial pour remplacer ce comportement pour une mise en page exacte.
AFAIK, C ne réorganise pas ou n’aligne pas la disposition mémoire d’une struct
par défaut. Cependant, j’ai entendu dire qu’il y avait une petite exception très difficile à trouver.
Quel est le comportement de la mémoire de C? Que faut-il réorganiser / aligner et non?
En C, le compilateur est autorisé à dicter un certain alignement pour chaque type primitif. L’alignement correspond généralement à la taille du type. Mais c’est entièrement spécifique à la mise en œuvre.
Les octets de remplissage sont introduits pour que chaque object soit correctement aligné. La réorganisation n’est pas autorisée.
Il est possible que chaque compilateur moderne à distance implémente #pragma pack
qui permet de contrôler le remplissage et laisse au programmeur le soin de se conformer à l’ABI. (Il est ssortingctement non standard, cependant.)
De C99 §6.7.2.1:
12 Chaque membre non-bit-field d’un object structure ou union est aligné d’une manière adaptée à son type.
13 Dans un object structure, les membres des champs non binarys et les unités dans lesquelles résident les champs binarys ont des adresses qui augmentent dans l’ordre dans lequel ils sont déclarés. Un pointeur vers un object de structure, converti de manière appropriée, pointe vers son membre initial (ou si ce membre est un champ de bits, puis vers l’unité dans laquelle il réside), et inversement. Il peut y avoir un remplissage non nommé dans un object de structure, mais pas au début.
C’est spécifique à la mise en œuvre, mais en pratique, la règle (en l’absence de #pragma pack
ou similaire) est:
sizeof(T)
octets sizeof(T)
. Donc, étant donné la structure suivante:
struct ST { char ch1; short s; char ch2; long long ll; int i; };
ch1
est à l’offset 0 s
au décalage 2 ch2
est au décalage 4, immédiatement après s ll
à l’offset 8 i
au décalage 16, juste après ll Donc sizeof(ST)
est 24.
Il peut être réduit à 16 octets en réorganisant les membres pour éviter le remplissage:
struct ST { long long ll; // @ 0 int i; // @ 8 short s; // @ 12 char ch1; // @ 14 char ch2; // @ 15 } ST;
Vous pouvez commencer par lire l’ article de Wikipédia sur l’ alignement de la structure de données pour mieux comprendre l’alignement des données.
De l’ article de Wikipedia :
L’alignement des données consiste à placer les données à un décalage de mémoire égal à un multiple de la taille du mot, ce qui augmente les performances du système en raison de la manière dont le processeur gère la mémoire. Pour aligner les données, il peut être nécessaire d’insérer des octets sans signification entre la fin de la dernière structure de données et le début de la suivante, qui est le remplissage de la structure de données.
From 6.54.8 Structure-Emballage Pragmas de la documentation GCC:
Pour assurer la compatibilité avec les compilateurs Microsoft Windows, GCC prend en charge un ensemble de directives #pragma qui modifient l’alignement maximal des membres des structures (autres que les champs de bits de largeur nulle), des unions et des classes définies ultérieurement. La valeur n ci-dessous doit toujours être une faible puissance de deux et spécifie le nouvel alignement en octets.
pragma pack (n) définit simplement le nouvel alignement.
pragma pack () définit l’alignement sur celui qui était dans
Effet lors du démarrage de la compilation (voir aussi l’option de ligne de commande -fpack-struct [=] voir Options de Code Gen).
pragma pack (push [, n]) pousse le paramètre d’alignement actuel sur un
stack interne et définit éventuellement le nouvel alignement.
pragma pack (pop) restaure le paramètre d’alignement sur celui enregistré dans
le haut de la stack interne (et supprime cette entrée de stack). Notez que
enter code here
#pragma pack ([n]) n’influence pas cette stack interne; il est donc possible d’avoir #pragma pack (push) suivi de plusieurs instances #pragma pack (n) et finalisé par un seul pack #pragma (pop).Certaines cibles, par exemple i386 et powerpc, prennent en charge le paramètre #pragma ms_struct qui présente une structure sous la forme de __atsortingbute__ ((ms_struct)) documentée.
pragma ms_struct active la disposition des structures déclarées.
pragma ms_struct désactive la disposition des structures déclarées.
pragma ms_struct reset revient à la mise en page par défaut.