Taille de la structure avec un caractère, un double, un int et à

Quand je lance seulement le fragment de code

int *t; std::cout << sizeof(char) << std::endl; std::cout << sizeof(double) << std::endl; std::cout << sizeof(int) << std::endl; std::cout << sizeof(t) << std::endl; 

ça me donne un résultat comme ça:

 1 8 4 4 

Total: 17

Mais lorsque je teste la structure sizeof qui contient ces types de données, j’en ai 24, et je suis confus. Quels sont les 7 octets supplémentaires?

C’est le code

 #include  #include  struct struct_type{ int i; char ch; int *p; double d; } s; int main(){ int *t; //std::cout << sizeof(char) <<std::endl; //std::cout << sizeof(double) <<std::endl; //std::cout << sizeof(int) <<std::endl; //std::cout << sizeof(t) <<std::endl; printf("s_type is %d byes long",sizeof(struct struct_type)); return 0; } 

:MODIFIER

J’ai mis à jour mon code comme ceci

 #include  #include  struct struct_type{ double d_atsortingbute; int i__atsortingbute__(int(packed)); int * p__atsortingbute_(int(packed));; char ch; } s; int main(){ int *t; //std::cout<<sizeof(char)<<std::endl; //std::cout<<sizeof(double)<<std::endl; //std::cout<<sizeof(int)<<std::endl; //std::cout<<sizeof(t)<<std::endl; printf("s_type is %d bytes long",sizeof(s)); return 0; } 

et maintenant il me montre 16 octets. Est-ce bien ou ai-je perdu des octets importants?

Il existe des octets inutilisés entre certains membres pour maintenir les alignements corrects . Par exemple, un pointeur réside par défaut sur des limites de 4 octets pour plus d’efficacité, c’est-à-dire que son adresse doit être un multiple de 4. Si la structure ne contient qu’un caractère et un pointeur

 struct { char a; void* b; }; 

alors b ne peut pas utiliser les additionneurs n ° 1 – il doit être placé à n ° 4.

  0 1 2 3 4 5 6 7 +---+- - - - - -+---------------+ | a | (unused) | b | +---+- - - - - -+---------------+ 

Dans votre cas, les 7 octets supplémentaires proviennent de 3 octets en raison de l’alignement d’ int* et de 4 octets en raison de l’alignement de double .

  0 1 2 3 4 5 6 7 8 9 abcdef +---------------+---+- - - - - -+---------------+- - - - - - - -+ | i |ch | | p | | +---------------+---+- - - - - -+---------------+- - - - - - - -+ 10 11 12 13 14 15 16 17 +-------------------------------+ | d | +-------------------------------+ 

… ça me donne 24 et je suis confus. Quels sont les 7 octets supplémentaires?

Ce sont des octets de remplissage insérés par le compilateur. Le remplissage de la structure de données dépend de la mise en œuvre.

D’après Wikipedia, alignement de la structure des données :

L’alignement des données consiste à placer les données à un décalage de la mémoire égal à un multiple de la taille du mot, ce qui augmente les performances du système en raison de la manière dont la CPU gère la mémoire. Pour aligner les données, il peut être nécessaire d’insérer des octets sans signification entre la fin de la dernière structure de données et le début du suivant, qui correspond au remplissage de la structure de données.

Pour développer légèrement l’excellente réponse de KennyDM (Kenny – volez ceci pour compléter votre réponse si vous le souhaitez), voici probablement à quoi ressemble votre structure de mémoire une fois que le compilateur a aligné toutes les variables:

  0 1 2 3 4 5 6 7 +-------------------+----+-----------+ | i | ch | (unused) | +-------------------+----+-----------+ 8 9 10 11 12 13 14 15 +-------------------+----------------+ | p | (unused) | +-------------------+----------------+ 16 17 18 19 20 21 22 23 +------------------------------------+ | d | +------------------------------------+ 

Ainsi, en raison de l’écart de 3 octets entre “ch” et “p”, et de 4 octets entre “p” et “d”, vous obtenez un remplissage de 7 octets pour votre structure, soit une taille de 24 octets. Comme le double votre environnement a un alignement de 8 octets (c’est-à-dire qu’il doit résider dans son propre bloc de 8 octets, comme vous pouvez le voir ci-dessus), la struct entière sera également alignée sur 8 octets, ce qui permettra même de réorganiser les variables ne modifieront pas la taille à partir de 24 octets.

C’est 24 octets à cause du bourrage. La plupart des compilateurs limitent les données à un multiple de sa taille. Ainsi, un entier de 4 octets est ajouté à un multiple de 4 octets. Un double de 8 octets est ajouté à un multiple de 8 octets. Pour votre structure, cela signifie:

 struct struct_type{ int i; // offset 0 (0*4) char ch; // offset 4 (4*1) char padding1[3]; int *p; // offset 8 (2*4) char padding1[4]; double d; // offset 16 (2*8) }s; 

Vous pouvez optimiser votre structure comme ça:

 struct struct_type{ double d; int i; int *p; char ch; }s; 

sizeof (s) == 17 sur la plupart des compilateurs (20 sur certains autres)

Le compilateur est autorisé à aligner les membres de la structure sur les adresses pour un access plus rapide. par exemple, des limites de 32 bits. Il est uniquement requirejs par la norme que les membres de l’object soient stockés dans l’ordre dans lequel ils ont été déclarés. Veillez donc toujours à utiliser sizeof et offsetof lorsque vous avez besoin d’une position exacte en mémoire.

La taille supplémentaire provient de l’alignement des données, c’est-à-dire que les membres sont alignés sur des multiples de 4 ou 8 octets.

Votre compilateur aligne probablement int et les pointeurs sur des multiples pour 4 octets et le double sur des multiples sur 8 octets.

Si vous déplacez le double à une position différente dans la structure, vous pourrez peut-être réduire la taille de la structure de 24 à 20 octets. Mais cela dépend du compilateur.

Parfois aussi, vous avez besoin de la structure pour maintenir l’ordre requirejs. Dans ce cas, si vous utilisez gcc, vous devez utiliser l’ __atsortingbute__((packed)) .

Voir aussi ceci pour plus d’informations.

9.2 / 12 états – “Les membres de données non statiques d’une classe (non-syndiquée) déclarée sans un spécificateur d’access intervenant sont alloués de sorte que les membres ultérieurs aient des adresses plus élevées dans un object de classe. L’ordre d’atsortingbution des membres de données non statiques séparés par un access -specifier n’est pas spécifié (11.1). Les exigences d’alignement d’implémentation peuvent empêcher deux membres adjacents de se voir atsortingbuer l’un à la suite de l’autre, pas plus que l’exigence d’espace pour la gestion des fonctions virtuelles (10.3) et des classes de base virtuelles (10.1). ”

Ainsi, tout comme pour sizeof (double) et sizeof (int), les décalages auxquels les membres de la structure seraient alignés ne sont pas spécifiés, sauf que les membres déclarés ultérieurement se trouvent à des adresses plus élevées.

Voir la liste de FAQ comp.lang.c · Question 2.12 :

Pourquoi mon compilateur laisse-t-il des trous dans les structures, gaspille-t-il de l’espace et empêche-t-il les entrées / sorties «binarys» vers des fichiers de données externes? Puis-je désactiver cette option ou contrôler l’alignement des champs de la structure?