Comment puis-je désactiver le rembourrage de la structure en C sans utiliser Pragma? P>
6 Réponses :
Autre des options de compilateur telles que Pragma Pack, vous ne pouvez pas, le rembourrage est dans la norme C.
Vous pouvez toujours tenter de réduire le remplissage en déclarant que les plus petits types durent dans la structure comme dans: P>
struct _foo { int a; /* No padding between a & b */ short b; } foo; struct _bar { short b; /* 2 bytes of padding between a & b */ int a; } bar;
Il n'y a pas de moyen standard de faire cela. L'État standard indique que le rembourrage peut être effectué à la discrétion de la mise en œuvre. À partir de C99 Chaque membre de champ non binaire d'une structure ou d'un objet union est aligné sur une manière définie par la mise en oeuvre appropriée à son type. p>
blockquote> Cela dit, il y a quelques choses que vous pouvez essayer. p> Le premier que vous avez déjà réduit, en utilisant La seconde est de commander vos champs en plus petit au plus petit. Commander tels que tous les types code> long code> suivi du troisièmement, vous pouvez définir vos types comme des tableaux Ce dernier porte quelques explications supplémentaires. Dites que vous avez une structure avec les champs dans l'ordre suivant: p> avec un rembourrage, vous pouvez vous retrouver avec les octets suivants: P> 6.7.2.1 Structure et Spécificateurs syndicaux Code>, paragraphe 12:
#pragma code> pour essayer et convaincre le compilateur de ne pas emballer. Dans tous les cas, ce n'est pas portable. Ni d'autres moyens spécifiques à la mise en œuvre, mais vous devez les vérifier comme il peut être nécessaire de le faire si vous avez vraiment besoin de cette capacité. P>
long code> des code>, puis tous les
int code>,
courte code> et enfin
Char code> Types. Cela fonctionnera habituellement car il est le plus souvent des types plus grands qui disposent des exigences d'alignement plus strictes. Encore une fois, pas portable. P>
Char code> et jeter les adresses pour vous assurer qu'il n'y a pas de remplissage. Mais gardez à l'esprit que certaines architectures ralentissent si les variables ne sont pas alignées correctement et d'autres encore échouera lamentablement (comme élever une erreur de bus et terminer votre processus, par exemple). P>
CIILLLL
Remarque, sur certains systèmes accédant à des adresses mal alignées ( int * plng = & (n.c [3]); int mylong = * plong; code>) échouera du tout (e. G. 68000 et bras échouera). Donc, le rembourrage est requis là-bas.
D'accord, @vovanium, d'où mon commentaire "échoue misérablement".
Sur certaines architectures, la CPU elle-même s'opposera si elle est invitée à travailler sur des données mal alignées. Pour contourner ce problème, le compilateur pourrait générer plusieurs instructions de lecture ou d'écriture alignées, de déplacer et de scinder ou de fusionner les différents bits. Vous pouvez raisonnablement vous attendre à ce qu'elle soit 5 ou 10 fois plus lente que la manipulation des données alignée. Mais la norme ne nécessite pas que les compilateurs soient prêts à faire cela ... Compte tenu du coût de la performance, il n'est tout simplement pas assez de demande. Les compilateurs prenant en charge le contrôle explicite sur le rembourrage offrent leurs propres pragmes précisément parce que les pragmes sont réservés aux fonctionnalités non standard. P>
Si vous devez travailler avec des données pératurées, envisagez d'écrire vos propres routines d'accès. Vous voudrez peut-être expérimenter des types nécessitant moins d'alignement (par exemple, utilisez Char / int8_t), mais il est toujours possible que par exemple. La taille des structures sera arrondi aux multiples de 4, qui frustreraient des structures d'emballage étroitement, auquel cas vous aurez besoin de mettre en œuvre votre propre accès pour la région de la mémoire complète. P>
Soit vous laisser compiler faire un rembourrage, soit le dire de ne pas utiliser #pragma, soit vous utilisez simplement un tas d'octets comme un tableau de caractères, et vous construisez toutes vos données par vous-même (changeant et ajout d'octets). C'est vraiment inefficace mais vous contrôlerez exactement la mise en page des octets. J'ai fait cela parfois préparant des paquets de réseau à la main, mais dans la plupart des cas, c'est une mauvaise idée, même si elle est standard. P>
Si vous voulez vraiment des structures sans rembourrage: définissez des types de données de rechange pour courts, int, long, etc., en utilisant des structures ou des classes composées uniquement de 8 octets bits. Composez ensuite vos structs de niveau supérieur à l'aide des types de données de remplacement.
La surcharge de l'opérateur de C ++ est très pratique, mais vous pourriez obtenir le même effet dans C utilisant des structures au lieu de classes. Les ci-dessous des implémentations de moulage et d'affectation supposent que la CPU peut gérer des entiers de 32 bits malalignés, mais d'autres implémentations pourraient accueillir des processeurs plus strictes. P>
Voici l'exemple de code: P>
#include <stdint.h> #include <stdio.h> class packable_int { public: int8_t b[4]; operator int32_t () const { return *(int32_t*) b; } void operator = ( int32_t n ) { *(int32_t*) b = n; } }; struct SA { int8_t c; int32_t n; } sa; struct SB { int8_t c; packable_int n; } sb; int main () { printf ( "sizeof sa %d\n", sizeof sa ); // sizeof sa 8 printf ( "sizeof sb %d\n", sizeof sb ); // sizeof sb 5 return 0; }
Nous pouvons désactiver le rembourrage de la structure en C Programme C en utilisant l'une des méthodes suivantes.
-> Utilisez __ attribut __ ((emballé)) code> derrière la définition de la structure. Pour par exemple, P>
struct node {
char x;
short y;
int z;
} __attribute__((packed));
Ceci est non standard. Que ce soit (et si oui comment) cela est possible dépend entièrement de la mise en œuvre de C que vous utilisez.
Je pense qu'il n'y a pas d'autre moyen de le faire.
Il peut y avoir une option de ligne de commande compilateur spécifique au compilateur.
"Fermer comme pas une vraie question"? Sérieusement? Certaines personnes semblent avoir une idée plutôt bizarre quant à ce qui constitue une vraie question Imnsho: - / Peut-être qu'ils pensent que l'OP est difficile et devrait simplement utiliser
#pragma code>. Mais devine quoi? Les pragmes individuels sont pas i> une partie de la norme (autre que les STDC). Il se peut que OP utilise un compilateur qui a i> no
#pragma pack code> et ils portent le code d'une plate-forme qui fait.
@Pax, plusieurs personnes (y compris vous) ont noté que la question ne peut pas être répondue complètement sans connaître le compilateur. Je pense que c'est exactement ce que "ne peut pas être répondu raisonnablement dans sa forme actuelle" signifie. J'encourage @manu à ajouter ces informations.
@Matthew Flaschen: "Vous ne pouvez pas le faire dans la norme C" semble être une réponse complète raisonnable à la question.
@JeremyP - Alors? Comment cela ne fait-il pas cela pas une vraie question? Si vous croyez que c'est la réponse, alors postez-le donc et ... Tada! Vous avez maintenant une question avec une réponse! (contradictant directement "ne peut pas être répondu") magique!
@Kragen, je pense que vous devriez à nouveau lire les échanges :-) Je suis assez certain que Jeremy et Jeremy d'accord I> les uns avec les autres ici.
@Kragen: Oui. Je suis de ton côté!
@Kragen: Et la raison pour laquelle je n'ai pas posté ma réponse est parce que quelqu'un d'autre (plusieurs essais d'autre) l'avaient déjà posté :)
@Jeremyp, oui je pense que j'aurais dû probablement avoir @ a obtenu mon commentaire à @matthew.