« Programmation C/Types avancés » : différence entre les versions
Contenu supprimé Contenu ajouté
→Manipulation : Suppression d'une phrase sans grand sens... |
→Alignement et bourrage (padding) : Clarifications (enfin, j'espère) |
||
Ligne 71 :
=== Alignement et bourrage (padding) ===
Il s'agit d'un concept relativement avancé, mais qu'il est bien de connaitre pour agir en connaissance de cause. Lorsqu'on déclare une structure, on pourrait naïvement croire que les champs se suivent les uns à la suite des autres en mémoire.
Considérez que nous travaillons sur un environnement où le « mot machine » fait 4 octets, et où un <tt>char</tt> occupe un octet, et <tt>int</tt> 4. considérez maintenant la structure suivante:
<source lang="c">
struct ma_structure {
char champ1; /*
int champ2; /*
char champ3; /*
};
</source>
On pourrait penser que cette structure
En fait, les compilateurs insèrent quasi toujours des octets entre les champs pour pouvoir les ''aligner'' sur
Dans le cas d'un ordinateur dit « 32 bits », par exemple (i.e. dont le processeur central utilise des ''registres'' de 32 bits), il est courant que la mémoire ne puisse être adressée directement que par « bloc » de 32 bits. En se représentant la mémoire comme un tableau continu, on peut tracer le dessin suivant:
<pre>
Ligne 99 ⟶ 101 :
Un autre compilateur (ou le même, appelé avec des options différentes) peut aussi placer <code>champ2</code> de <code>b</code> à <code>e</code>, et <code>champ3</code> en <code>f</code>, pour optimiser l'utilisation mémoire. Mais alors il devra générer un code plus complexe lors des accès à <code>champ2</code>, le matériel ne lui permettant pas de le faire directement.
Même si les options commandant l'utilisation de bourrage sont spécifiques à chaque compilateur, il peut s'avérer nécessaire de connaître la « distance » (''offset'') d'un champ par rapport au début de la structure, et ce, de manière portable. Pour cela il existe une fonction (en fait, macro), déclarée dans l'entête <code>stddef.h</code>:
<source lang="c">
Ligne 105 ⟶ 107 :
</source>
La valeur renvoyée est le nombre de
<source lang="c">
Ligne 111 ⟶ 113 :
</source>
Si <code>type</code> était un pointeur, il faudrait faire un déréférencement supplémentaire (ou éviter l'étoile dans la macro). À noter que, même si cette macro peut s'avérer contraignante (notamment lorsqu'on ne dispose que de type pointeur), il est quand même préférable de l'utiliser pour des raisons de portabilité.
Voici un petit exemple d'utilisation de cette macro
<source lang="c">
Ligne 120 ⟶ 122 :
struct ma_structure {
};
Ligne 136 ⟶ 138 :
</source>
Sur une architecture
<pre>L'offset de 'champ2' vaut 4.</pre>
|