Je n'ai pas de problème particulier, mais juste une question d'ordre général (ce qui pourra améliorer mon savoir en C).
J'apprend depuis peu, et en bidouillant des sizeof de struct par curiosité, j'ai remarqué quelque chose qui échappe ma logique.
Je réalise un sizeof d'une struct comprenant deux int (chez moi, un int fait 4 octets).
Je réalise un sizeof de ma struct et il me renvoie 8 octets, jusqu'a la tout va bien. Par curiosité je rajoute un char dans ma struct, puis je recompile. (on en est à 2 int et un char sans taille prédéfinit dans la struct). Je recompile, il me renvoie 12 octets (mon char rajoute donc 4 octets à la taille dans ma structure), alors que lorsque je fais :
printf("char = %d octets", sizeof(char));
Il m'indique qu'un char est.. 1 octets !
Donc je continue à enlever/rajouter, et je me rend compte que cette structure :
struct Test
{
int age;
int note;
char test;
char test2;
char test3;
};
correspond à 12 octets.
Bref, tout ça pour dire que lorsque je déclare des char sans taille, la taille en octets de la structure ne correspond pas directement aux sizeof individuels des char. Je me demandais pourquoi ?
Merci pour votre aide !
Bonne journée aux lecteurs de ce post.
- Edité par BetaDuCentaure 16 août 2021 à 18:09:06
Un char sans taille ? Un char a une taille : 1 byte (qui fait bien souvent un octet).
Pour ta question, c'est une histoire d'alignement des données, quand le système alloue ta structure, il l'alloue par tranche de 4 octets. Question d’efficacité. Si tu avais mis 5 char à la suite de tes deux int tu aurais donc une taille de 16.
Oui, enfin un char sans taille prédéfinit, donc oui, 1 octet.
Merci pour la réponse. Du coup, il l'alloue par tranche de 4 octets pour toutes les variables possibles ? Donc dans une structure, un char seul ne fera jamais 1 octet.
attention, la taille d'un char dépend du système cible ; un char fera CHAR_BIT bits. Sur les plateformes usuelles, CHAR_BIT vaut actuellement 8, il peut avoir une taille différente sur des systèmes plus exotiques.
D'une manière similaire l'alignement des données dépend de la plateforme cible. Pour certaines plateformes et pour certains compilos c'est configurable. Généralement l'alignement par défaut est celui qui donne les meilleures performances temps. L'alignement = contrainte sur l'adresse de départ d'une donnée.
La taille par défaut d'une structure va également dépendre de l'alignement mais également de l'ordre des champs …
@Yo@n97one a donné un bon lien pour l'explication.
Le type short est peu utilisé. Sur mon ordi, il vaut 2 octets. Si je fais une structure de 2 short, j'obtient 4 octets. Si je met 1 char entre les deux, j'obtiens 6 et non 8. Ça dépend en effet de l'implémentation du compilateur sur notre ordi.
Le Tout est souvent plus grand que la somme de ses parties.
En fait cela s’aligne sur la taille du plus grand.
ex :
struct s
{
long long i;
char x;
};
fera 16 octets pour des long long de 8 octets, il y a donc 8 octets pour le char (7 de perdu). mais il faut penser qu'on peut en faire des tableaux de notre structure et il faut garder l' alignement pour les éléments suivants du tableau.
Il existe la possibilité de préciser qu'on ne veut pas de padding, mais je n'ai plus la commande en tête.
C'est aussi pour ça qu'il vaut mieux regrouper les types entre eux. Une structure char / int / char sera plus volumineuse qu'une structure char/char/int :
int main(void)
{
struct s_toto
{
char a;
int b;
char c;
}toto;
struct s_tata
{
char a, b;
int c;
}tata;
printf("size toto = %d, size tata = %d\n", sizeof(toto), sizeof(tata));
return 0;
}
size toto = 12, size tata = 8
Et une structure char/char/char/char/int ne sera pas plus grande qu'une char/int.
Certains systèmes gèrent jusqu'au bit, un booléen déclaré va occuper 1 octet, alors autant déclarer tous les booléens à la suite pour occuper cet octet autant que possible.
bool/byte -> 2 octets.
bool (x8) / byte -> toujours 2 octets.
bool / byte / bool -> 3 octets.
Berf, pour limiter le padding, il faut penser à occuper du mieux possible l'espace disponible.
Bon, je suis encore loin d'avoir besoin d'optimiser mes octets à ce point, mais j'imagine que c'est parfois indispensable, notamment pour des programmes destinés à des systèmes embarqués qui n'ont que peu de mémoire vive. Intéressant d'avoir eu vos points de vue, merci à tous.
Après, désactiver l'alignement mémoire, c'est perdre en optimisation : les CPU sont par exemple optimisés pour traiter les variables 32 bits quand leur adresse est divisible par 4. Si ce n'est pas le cas, on peut imaginer que le CPU va faire ça en deux ou trois temps : peut être dans certains cas reconstruire le int 32 bit dans un registre avant de le traiter.
Mais tout cela est de la micro-optimisation : a moins d'être dans une zone très critique, on ne verra rien.
Pareil avec l'optimisation des structures, a moins d'en avoir un tableau énorme, et d'avoir donc des contraintes mémoires fortes, il n'est pas utile de compresser ainsi les structures.
Notez que je ne fais pas l'apologie du gaspillage de mémoire (qui me rend dingue quand on ouvre un onglet vide de chrome qu'il alloue presque 100 Mo), je dis juste qu'une optimisation est intéressante quand on gagne quelque chose de palpable à la fin.
Ce n'est pas forcément qu'une question d'optimisation de la mémoire.
Déjà, par pure estéthisme (mais là, c'est perso), regrouper par type me semble élégant. Ensuite, il y a le problème des personnes qui vont avoir tendance à sérialiser leurs structures dans les fichiers et produire des données poubelles voire des défauts de relecture (endianess, tailles des types toussa toussa...). Ce genre de souci n'est pas lié qu'à l'enregistrement du padding dans les fichiers, mais ce n'est quand-même pas terrible. Surtout quand on veut vérifier / débugger à l'éditeur héxa que notre fichier a été correctement construit.
Après, il faut s'en soucier ou pas. à une époque où la moindre photo pèse au bas mot 10Mo avec des définitions qu'aucun moniteur n'est capale d'afficher, qui se souci d'avoir un fichier 20% plus balaise que nécessaire ?
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Le Tout est souvent plus grand que la somme de ses parties.
Bonhomme !! | Jeu de plateforme : Prototype.
Recueil de code C et C++ http://fvirtman.free.fr/recueil/index.html
Bonhomme !! | Jeu de plateforme : Prototype.