12
votes

C / C ++ obtenir la taille de la structure

Aujourd'hui, avec ma grande surprise, j'ai découvert que

Lorsque la taille de l'opérateur est appliquée à un type de classe, de structure ou d'union, le résultat est le nombre d'octets dans un objet de ce type, plus tout rembourrage ajouté pour aligner les membres sur les limites de mots. Le résultat ne correspond pas nécessairement à la taille calculée en ajoutant les exigences de stockage des membres individuels. P> BlockQuote>

Je ne le savais pas et je suis sûr que cette chose brise une partie de mon ancien code: lire des fichiers binaires, j'avais l'habitude d'avoir des structures comme celle-ci: p> xxx pré>

et lire ces 6 octets directement avec Fread code> piloté par Tailleof code>: p>

fread( &header, sizeof(header), 1, f );


6 commentaires

Dupliquer possible de Pourquoi la taille d'une structure n'est-elle pas égale à la somme de la taille de chaque membre?


Juste une remarque: Standard-C n'autorise pas non plus les membres du syndicat Union ; En outre, les types standard de taille fixe (déclarés dans stdint.h ) sont appelés uint32_t et uint16_t


Serait utile de citer l'endroit où votre citation vint. Est-ce de la norme récente?


Devis issue de: MSDN.MicRosoft.com/en-us /Library/4s7x1k91(vs.71).aspx


Je sais que ce n'est pas la bonne façon de lire / écrire des données binaires: j'aurais un résultat différent en fonction de l'endianess de la machine. Quoi qu'il en soit, cette méthode est la plus rapide, je suis juviste à essayer de lire des données binaires pour obtenir rapidement son contenu, de ne pas écrire une application que je vais utiliser à l'avenir ou pour libérer.


En quelque sorte, je me demande si Knuth avait raison quand il a inventé "l'optimisation prématurée est la racine de tout mal", peut-être que cela aurait dû être "hypothèse est la racine de tout mal".


8 Réponses :


3
votes

Oui, le code que vous avez présenté n'est pas portable. Non seulement la taille des structures mais aussi les commandes d'octets peuvent différer.


0 commentaires

1
votes

La plupart des compiles fournissent une extension spécifique qui vous permet de contrôler l'emballage des structures. Cela devrait vous permettre de le contrôler. Cependant, lorsque vous écrivez la structure en binaire, vous devriez être capable de l'écrire et de le lire indépendamment de l'emballage, comme lorsque vous écrivez la structure, il devrait également écrire la taille de (struct) d'octets. Le seul cas où cela serait un problème, c'est si vous souhaitiez lire des fichiers créés avec les versions précédentes. En outre, vous devez considérer les problèmes d'ordre des octets, etc.


1 commentaires

Je n'ai pas généré les données binaires de la même manière. C'est un fichier dont j'avais besoin pour analyser rapidement.



9
votes

Ce que vous voulez, c'est la commande #pragma pack. Cela vous permet de définir l'emballage à n'importe quel montant que vous souhaitez. Généralement, vous définiriez la valeur d'emballage sur 1 (ou est-ce que 0?) Avant votre définition de la structure, puis retournez-la à la valeur par défaut après la définition.

Notez que cela ne fait rien pour garantir la transférabilité entre les systèmes.

Voir aussi: Utilisez-de-pragma-in-C et divers autres Questions sur SO


3 commentaires

C'est exactement ce dont j'avais besoin. Merci.


Cette réponse doit mentionner que c'est spécifique à l'hiver.


@R ..: En réalité, il travaille avec GCC sur Linux (oui, je l'ai testé sur les architectures x86, mais je ne vois pas pourquoi il ne devrait pas fonctionner avec GCC sur une autre plate-forme).



1
votes

Votre question est spécifique au compilateur, mais généralement si vous construisez votre structure de telle sorte que chaque membre se situe sur une limite de la même taille que celle de la même taille (quatre éléments d'octets sur les limites divisibles par quatre, etc.), vous obtiendrez le comportement. tu veux. Regardez également des cas comme celui que vous avez présenté où le rembourrage vient à la fin d'une structure pour aligner le début du premier élément de la structure suivante - si elles étaient disposées dans un tableau.


0 commentaires

1
votes

Il semble que vous ayez notamment posé une question à une question, donc je ne sais pas pourquoi je tente même de répondre! Mais oui, l'emballage est important et changera en fonction des versions du compilateur, des drapeaux, des pragmes d'architecture ciblées, de la direction du vent, des phases de la lune et potentiellement de nombreuses autres choses. Dumping binaire à un fichier (ou socket) n'est pas un très bon moyen de sérialiser quoi que ce soit.


1 commentaires

Eh bien, la principale question, en dehors des doutes sur le rembourrage, était la suivante: "Sinon, quel serait un moyen de lire une structure de données brutes d'un fichier qui n'a pas besoin d'écrire trop de code?"



0
votes

Oui, le problème d'alignement. C'est pourquoi les messages de protocole Internet ont des structures alignées afin que ce problème puisse être évité lors de l'envoi de données sur le réseau.

Ce que vous pouvez faire est de résoudre vos structures de sorte qu'elles soient alignées correctement ou que vous utilisez des fonctions de marshalling que vous utilisez lors de l'enregistrement et de la récupération de données.


0 commentaires

1
votes

Ce remplissage supplémentaire est nécessaire pour que les membres soient alignés correctement lorsque vous créez un tableau de ces structures. Sans cela, le 2e élément de la matrice aurait le Ident aligné sur une adresse qui n'est pas un multiple de 4.

Il est probablement trop tard pour faire quoi que ce soit à ce sujet, vous avez probablement écrit des fichiers avec cette structure avant. Changer l'emballage rendra ces fichiers illisibles. Mais oui, avoir des données de fichier dépendant des paramètres du compilateur n'est pas la plus grande idée. Avoir des données stockées dans un format lisible par l'homme est courant ces jours-ci. Ni les octets de disque ni les cycles de la CPU ne la valent.


2 commentaires

Je n'ai pas généré des données binaires de la même manière. C'est un fichier dont j'avais besoin pour analyser rapidement.


Eh bien, vous devez techniquement pour savoir quel emballage a été utilisé dans tout programme écrit les données. Vous saurez quand vous devez savoir, vous obtiendrez des valeurs de déchets. Typiquement des données écrites après cette structure.



2
votes

Ce n'est pas la bonne façon de traiter les fichiers binaires. Outre des problèmes d'alignement, il a également des problèmes de Endian. La bonne façon de lire des fichiers binaires est avec un tableau de uint8_t (ou sans signé Char , cela n'a pas vraiment d'importance) et vos propres fonctions à créer une représentation en mémoire hors des données.


0 commentaires