Alignement de données

[Résolu]
Signaler
Messages postés
452
Date d'inscription
jeudi 4 décembre 2003
Statut
Membre
Dernière intervention
19 décembre 2008
-
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
-
Cela fait maintenant plusieurs fois que je lis des commentaires sur l'alignement des données dans les structures.

Apres quelques recherches sur le sujet, je suis toujours autant perdu.

A quoi ça sert, comment ça marche, ou le mettre en oeuvre?



Voici un exemple que brunews a poster recemment sur une source:



sizeof(GRIDA) 12 alors que refaite correctement GRIDB 8:



typedef struct _GRIDA {

char coox;

char cooy;

int value;

bool flag;

} GRIDA;



typedef struct _GRIDB {

int value;

bool flag;

char coox;

char cooy;

} GRIDB;



Et bien, je ne comprends pas du tout comment GRIDB peut etre inferieur a GRIDA.

J'ai du sauter une etape, donc si vous pouviez me l'expliquer?

En fait, ce que je crois avoir compris de cet exemple: (xx est ce qui est rajoute pour l'alignement des données)

GRIDA: coox cooy xx xx | value value value value | flag xx xx xx = 12 octets

GRIDB: value value value value | flag coox cooy xx = 8 octets



Mais comment fait on alors pour dire sur quel taille aligner les données? (ici, j'ai l'impression que c'est 4).



Bref, j'espere que vous comprenez les questions que je me pose, parcque
elles sont tellement floues que j'ai moi meme du mal à les ecrire.

Vive le C
Tchao
[mailto:julienbj@hotmail.com Savon]

6 réponses

Messages postés
2671
Date d'inscription
vendredi 25 janvier 2002
Statut
Membre
Dernière intervention
6 février 2013
2
Si tu veux en C, une structure est considéré comme correcte et optimale, a partir du moment ou les données y sont alignées.
C'est a dire que les variables sont organisées dans un ordre décroissant selon leur taille (int = 4 octets, char 1 octet, ....)
Cela est du au fait que l'adressage des variables se fait en 32bits ( 4 octets).
Une structure mal agencé, force certains compilateurs a y ajouté des octets de bourage pour arriver a des plages de 4 octets pour chaque groupes de variables si nécéssaire, d'ou
l'interet d'aligner les variables au sein d'un structures, afin d'y gagner en performance.

Shell
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
29
Un compilo en mode par défaut (le mieux pour l'alignement correct) va aligner chaque membre d'une struct en fonction de son type et donc de sa taille. Le niveau d'alignement est de plus déterminé par le choix de la plateforme ciblée à la compilation, c'est par exemple 8 sur processeur 32 bits compatible Intel.
Je fais volontairement abstraction du cas où on spécifie une compil avec SSE(1 et 2), tu te reporteras aux manuels Intel si le sujet t'intéresse (align 16 minimal, offset de 32 mini dans le code entre chaque accès aux registres SSE, etc etc...), très vaste sujet.
http://brunews.free.fr/brunews/download/Intel.rar

Donc compil standard en mode 586:
- La struct (offset 0, le 1er membre) est alignée sur 8, transparent pour le développeur C.
- Chaque membre aura un alignement correspondant au minimum à sa taille:
-- 32 bits sur 4
-- double sur 8
-- 16 bits sur 2
-- 8 bits sur 1

Partant de cela, le compilo aura donc transcrit ainsi la 1ere struct:
typedef struct _GRIDA {
char coox;
char cooy;
char cadrage[2];
int value; // AINSI OK EST BIEN SUR 4
bool flag; // 1 octet en C++
char cadrage2[3]; // REMPLISSEUR MINIMAL POUR DONNEES SUIVANTES DU REGISTRE .data
} GRIDA;
ce qui fait logiquement sizeof = 12.

GRIDB ne se voit ajouter qu'1 seul octet de remplissage à la fin, ce qui fait bien 8 alors qu'on a bien les mêmes membres, simplement en ayant placé (aligné) correctement les données.

Ne pas croire que tout ceci est pure fantaisie des concepteurs de compilo, le choix est d'ailleurs laissé au developpeur de modifier l'alignement (#prama PACK()) mais c'est normalement à bannir dans un prog en mode user tant qu'on n'a pas à mettre une struct en conformité avec les specs d'un driver.Un DWORD non aligné sur 4 par exemple et accédé directement (int x tabInt[2]; par exemple> MOV asm) sera sanctinné par une faute d'alignement émise par le cpu (que Windows récupèrera seul comme un grand, Linux idem je crois) et restera transparent pour le développeur MAIS se traduira par des cycles de pénalité et réduira donc fortement les performances.

ciao...
http://dev.winsysdev.com
BruNews, MVP VC++
Messages postés
452
Date d'inscription
jeudi 4 décembre 2003
Statut
Membre
Dernière intervention
19 décembre 2008
13
OK, je vais mediter tout ca.

Ca fait pas mal d'infos en un soir.

Je reviendrai certainement à la quete aux détails (je risque de pas
tout comprendre dans la doc intel -> Je l'avais deja recupérée et
m'étais un peu embrouillé les pinceaux avec )

Merci en tout cas pour toutes ces infos, je vais aller jeter un oeil de
suite à mes structures, car c'est un moyen assez simple d'accélerer son
code (ou plutot de ne pas trop le ralentir).

Vive le C
Tchao
[mailto:julienbj@hotmail.com Savon]
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
29
Certaines structs de driver sont en PACK(1) donc avec membres non alignés, le but est le gain de place ou alors la conformité et la continuité avec d'anciennes normes matérielles.
Si on doit bosser avec de telles structs il convient de les recopier vers des structs alignées si on doit faire de nombreux calculs dessus (copie octet par octet grace aux pointeurs).

ciao...
http://dev.winsysdev.com
BruNews, MVP VC++
Messages postés
452
Date d'inscription
jeudi 4 décembre 2003
Statut
Membre
Dernière intervention
19 décembre 2008
13
Alors si le but est la compatibilité avec l'ancien, le désalignement de donnée est-il appelé à disparaitre? Le "vieux" étant de moins en moins maintenu, on peut s'attendre à ce que ces définitions de PACK(1) disparaissent, sauf s'il est envisagé une compatibilité permanente avec ce "vieux".
Je sais, la question est plus philosophique que technique. Ce ne sont que des présomptions, mais ...

Vive le C
Tchao
[mailto:julienbj@hotmail.com Savon]
Messages postés
21041
Date d'inscription
jeudi 23 janvier 2003
Statut
Modérateur
Dernière intervention
21 août 2019
29
Mais c'est très clair, dans les structs du DDK on ne trouve plus guère de struct avec PACK(1) qui ne soit directement concernée par le matériel et heureusement.

ciao...
http://dev.winsysdev.com
BruNews, MVP VC++