Question

J'ai un C # fond. Je suis très bien un débutant à un langage de bas niveau comme C.

En C #, la mémoire de struct est aménagé par le compilateur par défaut. Le compilateur peut réordonner des champs de données ou pad bits supplémentaires entre les champs implicitement. Donc, je devais spécifier un attribut spécial pour modifier ce comportement pour la mise en page exacte.

AFAIK, C ne mise en mémoire ne Réorganiser ou d'un alignement struct par défaut. Cependant, j'ai entendu il y a une petite exception qui est très difficile à trouver.

Quel est le comportement de mise en page de mémoire C? Ce qui devrait être réorganisée / aligné et non?

Était-ce utile?

La solution

En C, le compilateur est autorisé à dicter un certain alignement pour chaque type primitif. Typiquement, l'alignement est la taille de ce type. Mais il est tout à la mise en œuvre spécifique.

octets de Rembourrage sont introduits de sorte que chaque objet est correctement aligné. ReOrdering n'est pas autorisé.

Peut-être tous les outils du compilateur à distance moderne #pragma pack qui permet le contrôle de rembourrage et laisse au programmeur de se conformer à l'ABI. (Il est strictement non standard, cependant.)

De C99 §6.7.2.1:

  

12 Chaque membre non-champ binaire d'un   la structure ou de l'objet est aligné union   d'une manière définie l'implémentation   adaptée au type.

     

Dans un 13   objet de structure, le champ non-bit   les membres et les unités dans lesquelles   champs de bits résident ont adresses   augmentation de l'ordre dans lequel ils   sont déclarés. Un pointeur vers une structure   objet, converti de manière appropriée, des points de   son élément initial (ou si ce membre   est un champ binaire, puis à l'unité   lequel il se trouve), et vice versa.   Il peut y avoir des remplissages sans nom dans un   objet structure, mais pas à sa   début.

Autres conseils

spécifique de mise en œuvre, mais dans la pratique la règle (en l'absence de #pragma pack ou similaire) est:

  • Les membres sont stockés dans Struct l'ordre dans lequel ils sont déclarés. (Ceci est requis par la norme C99, comme mentionné ici auparavant.)
  • Si nécessaire, le rembourrage est ajouté avant chaque membre struct, afin d'assurer un alignement correct.
  • Chaque type primitif T nécessite un alignement d'octets de sizeof(T).

Alors, compte tenu de la struct suivante:

struct ST
{
   char ch1;
   short s;
   char ch2;
   long long ll;
   int i;
};
  • ch1 est à la position 0
  • un octet de bourrage est inséré pour aligner ...
  • s à décalage 2
  • ch2 est à décalage 4, immédiatement après s
  • 3 octets de bourrage sont insérés à aligner ...
  • ll à 8 décalage
  • i est à 16 décalage, juste après ll
  • 4 octets de remplissage sont ajoutés à la fin de sorte que la structure globale est un multiple de 8 octets. Je vérifié ceci sur un système 64 bits. Les systèmes 32 bits peuvent permettre d'avoir un alignement structs 4 octets

sizeof(ST) est 24.

Il peut être réduit à 16 octets en réorganisant les membres à éviter padding:

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 wikipedia d'alignement de la structure de données pour obtenir une meilleure compréhension des l'alignement des données.

De la wikipedia article :

  

des moyens d'alignement de données mettant les données à une mémoire de décalage égal à un multiple de la taille de mot, ce qui augmente les performances du système en raison de la façon dont la poignée de la CPU mémoire. Pour aligner les données, il peut être nécessaire d'insérer des octets vides de sens entre la fin de la dernière structure de données et le début de la prochaine, qui est le rembourrage de structure de données.

De 6.54.8 Structure-emballage Pragmas du CCG documentation:

  

Pour la compatibilité avec Microsoft   compilateurs Windows, GCC prend en charge un ensemble   des directives #pragma qui changent la   alignement maximal de membres de   structures (autres que zéro largeur   bitfields), les syndicats et les classes   ensuite définie. La valeur de n   ci-dessous est toujours nécessaire d'être un petit   puissance de deux et précise la nouvelle   alignement en octets.

     
      
  1. #pragma pack(n) définit simplement le nouvel alignement.
  2.   
  3. #pragma pack() définit l'alignement de celui qui était en   effet quand a commencé la compilation (voir   commander également l'option de ligne   -fpack-struct [=] Voir le code Gen Options).
  4.   
  5. #pragma pack(push[,n]) pousse le réglage d'alignement en cours sur une   pile interne et ensuite éventuellement   définit le nouvel alignement.
  6.   
  7. #pragma pack(pop) rétablit le réglage d'alignement à celle enregistrée au   le sommet de la pile interne (et   supprime cette entrée de pile). Notez que   #pragma pack([n]) n'a aucune influence sur cette pile interne; il est donc   possible d'avoir #pragma pack(push)   suivie par multiple #pragma pack(n)   instances et mis au point par un seul   #pragma pack(pop).
  8.   
     

Certaines cibles, par exemple i386 et powerpc,   soutenir la #pragma de ms_struct qui   expose une structure comme documentée   __attribute__ ((ms_struct)).

     
      
  1. tourne #pragma ms_struct on sur la mise en page pour les structures déclaré.
  2.   
  3. tourne #pragma ms_struct off au large de la mise en page pour les structures déclaré.
  4.   
  5. #pragma ms_struct reset retourne à la mise en page par défaut.
  6.   
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top