10
votes

Alignement des membres de la structure - est-il possible d'assumer aucun rembourrage

Imaginez une structure composée de valeurs de membre 32 bits, 16 bits et 8 bits. Lorsque la commande des valeurs de membre est telle que chaque membre est sur sa limite naturelle.

struct Foo
{
    uint32_t a;
    uint16_t b;
    uint8_t c;
    uint8_t d;
    uint32_t e;
};


3 commentaires

Dans C, FOO , dans Tailleof (FOO) , n'est pas déclaré. L'expression est une erreur (sauf si foo est défini / déclaré ailleurs ailleurs). Je vous suggère que vous n'essayez pas d'écrire des fichiers source multilingues: les inconvénients sont beaucoup plus gros que tout pro vous pourriez trouver.


@PMG: pédantisme. :) Typeft struct foo {...} foo;


Je crois que le Typedef est redondant (et donc une source de bugs amovible en toute sécurité) en C ++. Mon point reste: écrire des fichiers sources multilingues est plus de problèmes que cela vaut la peine.


3 Réponses :


6
votes

sur des systèmes qui offrent réellement ces types, il est très susceptible de fonctionner. On dit qu'un système 36 bits Ces types ne seraient pas disponibles en premier lieu.

GCC fournit un attribut

__ attribut__ ((emballé))

avec effet similaire.


3 commentaires

Ce n'est pas vraiment dépendant de la dépendance, mais plutôt de l'architecture dépendante. Par exemple, certains processeurs 16 ou 32 bits ne peuvent pas adresser directement une adresse 8 bits, il peut donc nécessiter de générer des instructions de décalage et de masque supplémentaires pour extraire une valeur de 8 bits à partir d'une mémoire de 16 ou 32 bits. Cette situation est beaucoup plus commune que votre système hypothétique 36 bits (ARM7 par exemple).


@Clifford: Ce n'est pas courant. Le compilateur doit déjà générer du code permettant d'adresser un type 8 bits s'il existe (car il ne peut jamais être aligné dans des tableaux), ce n'est donc pas une contrainte supplémentaire. En général, "l'alignement" d'un type ne peut jamais être plus grand que sa taille (et doit diviser sa taille), il serait donc pathologique pour un compilateur pour imposer un alignement plus important lorsque le type est utilisé dans une structure.


Je ne disait pas que le compilateur ne pouvait pas ou ne générerait pas de code pour des accès 8 bits si nécessaire, plutôt pour des raisons de performance, il l'éviterait pour une structure. Un tableau est garanti d'être contigu, une structure n'est pas. Je suggérerais que ARM7 soit assez commun, mais comme il est tagué Linux, pas tellement dans ce contexte.



7
votes

En général, vous êtes correct que ce n'est pas une hypothèse sûre, bien que vous obteniez souvent l'emballage que vous attendez sur de nombreux systèmes. Vous pouvez utiliser l'attribut emballé code> de vos types lorsque vous utilisez GCC.

E.g. P>

struct __attribute__((packed)) Blah { /* ... */ };


1 commentaires

Ceci est plutôt dangereux et totalement inutile. Voir ma réponse.



7
votes

Dans la pratique, sur tout système où les types uintxx_t existent, vous obtiendrez l'alignement souhaité sans aucun rembourrage. Ne jetez pas dans la vidéographie GCC-ISM pour essayer de le garantir.

EDIT: Pour élaborer pourquoi il peut être nocif pour utiliser attribut emballé ou aligné , il peut causer la structure entière être mal aligné lorsqu'il est utilisé comme membre d'une structure plus grande ou sur la pile. Cela va certainement faire mal aux performances et, sur des machines non-X86, générera un code beaucoup plus vaste. Cela signifie également qu'il est invalide de prendre un pointeur sur n'importe quel membre de la structure, puisque le code qui accède à la valeur via un pointeur ne sera pas conscient qu'il pourrait être mal aligné et peut donc faire défaut.

Quant pourquoi il est inutile, gardez à l'esprit que attribut est spécifique aux compilateurs de GCC et de GCC-Workalike. La norme C ne laissait pas l'alignement non défini ou non spécifié. C'est défini par la mise en œuvre , ce qui signifie que la mise en œuvre est requise pour spécifier et documenter comment il se comporte. Le comportement de GCC est et a toujours été, d'aligner chaque membre de la structure à la limite suivante de son alignement naturel (le même alignement qu'il aurait été utilisé en dehors d'une structure, ce qui est nécessairement un nombre qui divise uniformément la taille du type) . Étant donné que attribut est une fonction GCC, si vous utilisez-le, vous supposez déjà un compilateur de type GCC, mais par hypothèse, vous avez l'alignement que vous souhaitez déjà.


1 commentaires

Avec C11, vous pouvez également _static_assert que la taille de la structure est ce que vous attendez.