Pourquoi n'est-ce pas sizeof pour une struct égale à la somme de sizeof de chaque membre?
Pourquoi le sizeof
opérateur renvoie une taille plus grande pour une structure que le total des tailles de la structure de membres?
- Voir cette FAQ C sur la mémoire alighnment. c-faq.com/struct/align.esr.html
- Anecdote: Il y avait une réelle virus informatique qui a mis son code à l'intérieur de struct des remplissages dans le programme d'accueil.
- C'est impressionnant! Je n'aurais jamais pensé possible l'utilisation de ces petites zones pour quoi que ce soit. Êtes-vous en mesure de fournir plus de détails?
- Je suis sûr qu'il a impliqué beaucoup de jmp.
- Voir la structure remplissage, l'emballage: L'Art Perdu de la Structure C Emballage Eric S. Raymond
SO, answer
,Geeks4Geeks
, lien- Ne rembourrage existent entre les 2 struct ainsi de faire le premier membre de la prochaine struct pour commencer à une adresse alignée?
- Les deux structures vont commencer alignés (sauf si vous leur causer de ne pas être...byte-sage serializations, etc.)
Vous devez vous connecter pour publier un commentaire.
C'est à cause de rembourrage ajoutée pour satisfaire les contraintes d'alignement. La structure de données d'alignement impacts à la fois de la performance et de l'exactitude de programmes:
SIGBUS
).Voici un exemple d'utilisation typique des paramètres pour un processeur x86 (toutes utilisées en mode 32 et 64 bits):
On peut réduire la taille des structures de trier les membres par l'alignement (tri par taille suffit pour que dans les types de base) (comme la structure
Z
dans l'exemple ci-dessus).REMARQUE IMPORTANTE: le C et C++ normes indiquent que la structure de l'alignement de la mise en œuvre est définie. Par conséquent, chaque compilateur peut choisir d'aligner les données différemment, résultant dans différents et incompatibles des présentations de données. Pour cette raison, lorsque vous traitez avec les bibliothèques qui seront utilisés par les différents compilateurs, il est important de comprendre comment les compilateurs d'harmoniser les données. Certains compilateurs ont de la ligne de commande paramètres et/ou spéciaux
#pragma
états à modifier la structure des paramètres d'alignement.char
il y a 3 octets de remplissage, et pour les 2, il y a seulement 1 octet?X
, il y a 2 octets de remplissage après lashort
pour assurer le 4 octetsint
démarre sur un 4 limite d'octets. DansY
, il y a 1 octet de remplissage après lachar
assurez-vous que le 2 octetsshort
commence sur une frontière d'octet 2. Car le compilateur ne peut pas savoir ce qui pourrait être après un struct dans la mémoire (et il pourrait être beaucoup de choses différentes), il se prépare pour le pire et insère rembourrage suffisant pour faire de cette structure un multiple de 4 octets.X
besoin de 3 octets pour arriver à 12,Y
seulement besoin de 1 pour 8.struct {long long a; char b;}
généralement a 7 octets de remplissage à la fin, aprèsb
, rendant 16 octets au total. (sur la plupart des architectures 64 bits, yada yada)L'emballage et l'alignement d'octets, comme décrit dans la FAQ C ici:
Si vous voulez la structure pour avoir une certaine taille avec GCC, par exemple, utiliser
__attribute__((emballé))
.Sur Windows, vous pouvez définir l'alignement sur un octet lors de l'utilisation de la cl.exe compier avec le /Zp option.
Habituellement, il est plus facile pour le CPU d'accéder à des données qui est un multiple de 4 (ou 8), en fonction de la plate-forme et aussi sur le compilateur.
C'est donc une question de l'alignement de coeur.
Vous devez avoir de bonnes raisons de le changer.
__attribute__((packed))
est potentiellement dangereux dans certains cas: stackoverflow.com/q/8568432/827263#pragma pack
, de le faire avec une option de ligne de commande est mal. (GCC et clang sur Windows utiliser__attribute__
comme sur n'importe quel autre OS)Cela peut être dû à l'alignement d'octets et de rembourrage de telle manière que la structure sort pour un même nombre d'octets (ou des mots) sur votre plate-forme. Par exemple en C sur Linux, les 3 structures:
Les membres de la taille (en octets) de 4 octets (32 bits), 8 octets (2x 32 bits) et 1 octet (2+6 bits), respectivement. Le programme ci-dessus (sur Linux avec gcc) imprime les tailles 4, 8, et 4 - où la dernière structure est matelassée pour qu'il est un seul mot (4 x 8 bits des octets sur ma plate-forme 32 bits).
:2
et:6
sont réellement la spécification 2 et 6 bits, pas 32 bits entiers dans ce cas. someBits.x, en étant à seulement 2 bits ne peut stocker que de 4 valeurs possibles: 00, 01, 10 et 11 (1, 2, 3 et 4). Est-il logique? Voici un article à propos de la fonction: geeksforgeeks.org/bit-fields-cVoir aussi:
pour Microsoft Visual C:
http://msdn.microsoft.com/en-us/library/2e70t5y1%28v=vs.80%29.aspx
et CGC demande la compatibilité avec Microsoft compilateur.:
http://gcc.gnu.org/onlinedocs/gcc/Structure_002dPacking-Pragmas.html
En plus de la réponse à la question précédente, veuillez noter que, quel que soit l'emballage, il n'y a pas de membres-commande-garantie en C++. Les compilateurs peuvent (et certainement) ajouter virtuel le pointeur de la table et de la base de structures membres de la structure. L'existence même de la table virtuelle n'est pas assurée par la norme (virtuel mécanisme de mise en œuvre n'est pas spécifié) et, par conséquent, on peut conclure que cette garantie est tout simplement impossible.
Je suis tout à fait sûr membre de l'ordre est garantis dans C, mais je ne voudrais pas compter sur elle lors de l'écriture d'une croix-plate-forme ou de cross-compilateur programme.
La taille d'une structure est plus grand que la somme de ses parties, en raison de ce qui est appelé l'emballage. Un processeur particulier a préféré la taille des données qu'il fonctionne avec. La plupart des processeurs modernes préféré de taille de 32 bits (4 octets). Accéder à la mémoire lorsque les données sont sur ce type de limite est plus efficace que des choses qui dépassent cette limite de taille.
Par exemple. Examiner la structure simple:
Si la machine est une machine 32 bits de données et est aligné sur une frontière de 32 bits, nous voyons un problème immédiat (en supposant qu'aucune structure d'alignement). Dans cet exemple, nous supposons que la structure de données commence à l'adresse 1024 (0x400 - à noter que le plus faible de 2 bits sont à zéro, de sorte que les données sont alignées par rapport à la limite de 32 bits). L'accès aux données.une fonctionneront bien parce qu'il démarre sur une frontière - 0x400. L'accès aux données.b fonctionne également très bien, car il est à l'adresse 0x404 - une autre limite de 32 bits. Mais un non alignés structure de placer des données.c à l'adresse 0x405. Les 4 octets de données.c sont à 0x405, 0x406, 0x407, 0x408. Sur une machine 32 bits, le système serait de lire les données.c pendant un cycle de la mémoire, mais seulement obtenir 3 des 4 octets (le 4e octet est sur la prochaine frontière). Ainsi, le système de aurait à faire un deuxième accès à la mémoire pour obtenir le 4e octet,
Maintenant, si au lieu de mettre des données.c à l'adresse 0x405, le compilateur collier de la structure par 3 octets et mettre les données.c à l'adresse 0x408, le système aurait besoin que de 1 cycle pour lire les données, la coupe de temps d'accès à cet élément de données de 50%. Rembourrage swaps de mémoire de l'efficacité pour l'efficacité du traitement. Étant donné que les ordinateurs peuvent avoir d'énormes quantités de mémoire (plusieurs gigaoctets), les auteurs estiment que le swap (vitesse au-dessus de la taille) est raisonnable.
Malheureusement, ce problème devient un tueur lorsque vous tentez d'envoyer des structures sur un réseau ou même écrire des données binaires dans un fichier binaire. Le rembourrage inséré entre les éléments d'une structure ou une classe qui peuvent perturber les données envoyées vers le fichier ou le réseau. Afin d'écrire du code portable (celui qui va aller à plusieurs différents compilateurs), vous aurez probablement à accéder à chaque élément de la structure séparément pour assurer le bon "emballage".
D'autre part, les différents compilateurs ont des capacités différentes pour gérer les données de la structure de l'emballage. Par exemple, dans Visual C/C++ le compilateur prend en charge la directive #pragma pack de commande. Cela vous permettra d'ajuster les données de l'emballage et de l'alignement.
Par exemple:
Je devrais maintenant avoir la longueur de 11. Sans le pragma, je pourrais être n'importe quoi à partir de 11 à 14 ans (et pour certains systèmes, 32), en fonction du défaut d'emballage du compilateur.
#pragma pack
. Si des membres sont affectées de leur alignement par défaut, je voudrais dire en général la structure est pas paniers.Il peut le faire si vous avez implicitement ou explicitement définir l'alignement de la structure. Une structure qui est aligné 4 sera toujours un multiple de 4 octets, même si la taille de ses membres serait quelque chose qui n'est pas un multiple de 4 octets.
Également une bibliothèque peut être compilé sous x86 32 bits ints et vous pouvez peut-être en comparant ses composants sur un processus 64 bits serait serait de vous donner un résultat différent si vous le faisiez à la main.
C99 N1256 projet de norme
http://www.open-std.org/JTC1/SC22/WG14/www/docs/n1256.pdf
6.5.3.4 L'opérateur sizeof:
6.7.2.1 de la Structure et de l'union des prescripteurs:
et:
La nouvelle C99 souple tableau caractéristique de l' (
struct S {int is[];};
) peuvent aussi affecter padding:L'annexe J des Problèmes de Portabilité réitère:
C++11 N3337 projet de norme
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2012/n3337.pdf
5.3.3 Sizeof:
9.2 les membres de la Classe:
Je sais seulement assez de C++ pour comprendre la remarque 🙂
En plus des autres réponses, une structure peut (mais n'est généralement pas) ont des fonctions virtuelles, auquel cas la taille de la structure comprendra également un espace pour la vtbl.
Langage C feuilles compilateur d'une certaine liberté quant à l'emplacement des éléments de structure dans la mémoire:
Le langage C fournit l'assurance pour le programmeur d'éléments de mise en page dans la structure:
Problèmes liés aux éléments d'alignement:
Comment l'alignement des œuvres:
fin de sorte que le premier élément de la prochaine structure n'est pas la violer les exigences d'alignement
p.s infos Plus détaillées sont disponibles ici: "Samuel P. Harbison, Guy L. Steele C Une Référence, (5.6.2 - 5.6.7)"
L'idée est que pour la vitesse et la cache considérations, les opérandes doivent être lus à partir d'adresses alignés à leur taille normale. Pour ce faire, le compilateur plaquettes de membres de structure de sorte que le membre ou la structure suivante sera aligné.
L'architecture x86 a toujours été en mesure de récupérer mal alignées adresses. Cependant, il est plus lent et lorsque le désalignement chevauche deux différentes lignes de cache, puis il expulse deux lignes de cache lors de l'alignement de l'accès uniquement expulser un.
Certaines architectures en fait piéger sur alignées les lectures et les écritures, et les premières versions de l'architecture ARM (celui qui a évolué dans tous les Processeurs mobiles) ... bien, en fait ils ont juste de rentrer de mauvaises données sur ceux-ci. (Ils ont ignoré les bits de bas.)
Enfin, notez que les lignes de cache peut être arbitrairement grand, et le compilateur ne pas essayer de deviner ceux-ci ou de créer un espace-vs-vitesse. Au lieu de cela, l'alignement des décisions font partie de l'ABI et de représenter le minimum de l'alignement, qui va finalement uniformément remplir une ligne de cache.
TL;DR: l'alignement est important.