2 votes

Pourquoi le court est stocké comme 4 octets dans un struct en C ?

J'ai les deux structs suivants :

Le problème est que sizeof(Content) renvoie 160. La structure est composée de 11 shorts, 6 ints, 76 chars, 7 floats, 1 double, soit un total de 158 octets. J'ai compté trois fois et il y a toujours une différence de 2 octets.

typedef struct TIME_T { 
    short year,mon,day; 
    short hour,min,sec; 
} TIME;

typedef struct { 
    int no; 
    char name[20]; 
    char Code[10]; 
    char DASType[10]; 
    short wlen; 
    float VLtd; 
    int samp; 
    int comp; 
    int locationID; 
    short TranMode; 
    char TranIns[12]; 
    short TimerMode; 
    char ClkType[12]; 
    float ClkErr; 
    float lat; 
    float lon; 
    float alt; 
    float azimuth,incident; 
    short weight; 
    short veloc; 
    int oritype; 
    char seismometer[12]; 
    double sens; 
    TIME start_time; 
    int record_samples; 
} Content;

J'écris un petit bout de code pour imprimer la position de chaque variable dans la structure, et soudain je trouve la float wlen prend 4 octets. Mon code est le suivant :

int main(void)
{   
    Content content;
    printf("Sizeof Content: %d\n", sizeof(content));
    printf("Sizeof int content.no: %d\n", (int)&content.name - (int)&content.no);
    printf("Sizeof char[20] content.name: %d\n", (int)&content.Code - (int)&content.name);
    printf("Sizeof char[10] content.Code: %d\n", (int)&content.DASType - (int)&content.Code);
    printf("Sizeof char[10] content.DASType: %d\n", (int)&content.wlen - (int)&content.DASType);
    printf("Sizeof short content.wlen:  %d\n", (int)&content.VLtd - (int)&content.wlen);
    printf("Sizeof float content.VLtdL %d\n", (int)&content.samp - (int)&content.VLtd);
    printf("Sizeof int content.samp: %d\n", (int)&content.comp - (int)&content.samp);
    printf("Sizeof int content.comp: %d\n", (int)&content.locationID - (int)&content.comp);
    printf("Sizeof int content.locationID: %d\n", (int)&content.TranMode - (int)&content.locationID);
    printf("Sizeof short content.TranMode: %d\n", (int)&content.TranIns - (int)&content.TranMode);
    printf("Sizeof char[12] content.TranIns: %d\n", (int)&content.TimerMode - (int)&content.TranIns);
    printf("Sizeof short content.TimerMode: %d\n", (int)&content.ClkType - (int)&content.TimerMode);
    printf("Sizeof char[12] content.ClkType: %d\n", (int)&content.ClkErr - (int)&content.ClkType);
    printf("Sizeof float content.ClkErr: %d\n", (int)&content.lat - (int)&content.ClkErr);
    printf("Sizeof float content.lat: %d\n", (int)&content.lon - (int)&content.lat);
    printf("Sizeof floatcontent.lon: %d\n", (int)&content.alt - (int)&content.lon);
    printf("Sizeof floatcontent.alt: %d\n", (int)&content.azimuth - (int)&content.alt);
    printf("Sizeof floatcontent.azimuth: %d\n", (int)&content.incident - (int)&content.azimuth);
    printf("Sizeof floatcontent.incident: %d\n", (int)&content.weight - (int)&content.incident);
    printf("Sizeof short content.weight: %d\n", (int)&content.veloc - (int)&content.weight);
    printf("Sizeof short content.veloc: %d\n", (int)&content.oritype - (int)&content.veloc);
    printf("Sizeof int content.oritype: %d\n", (int)&content.seismometer - (int)&content.oritype);
    printf("Sizeof char[12] content.seismometer: %d\n", (int)&content.sens - (int)&content.seismometer);
    printf("Sizeof double content.sens: %d\n", (int)&content.start_time - (int)&content.sens);
    printf("Sizeof TIME content.start_time: %d\n", (int)&content.record_samples - (int)&content.start_time);
    printf("Sizeof int content.record_samples: %d\n", sizeof(content.record_samples));

    getchar();
    return 0;
}

Le résultat est le suivant :

Sizeof int content.no: 4
Sizeof char[20] content.name: 20
Sizeof char[10] content.Code: 10
Sizeof char[10] content.DASType: 10
Sizeof short content.wlen:  4
**Sizeof float content.VLtdL 4**
Sizeof int content.samp: 4
Sizeof int content.comp: 4
Sizeof int content.locationID: 4
Sizeof short content.TranMode: 2
Sizeof char[12] content.TranIns: 12
Sizeof short content.TimerMode: 2
Sizeof char[12] content.ClkType: 12
Sizeof float content.ClkErr: 4
Sizeof float content.lat: 4
Sizeof floatcontent.lon: 4
Sizeof floatcontent.alt: 4
Sizeof floatcontent.azimuth: 4
Sizeof floatcontent.incident: 4
Sizeof short content.weight: 2
Sizeof short content.veloc: 2
Sizeof int content.oritype: 4
Sizeof char[12] content.seismometer: 12
Sizeof double content.sens: 8
Sizeof TIME content.start_time: 12
Sizeof int content.record_samples: 4

Le compilateur est MSVC8, pas d'UNICODE défini, pas d'autre macro définie. C'est x86.

J'ai essayé de compiler le même code dans gcc version 3.4.4, la sortie est la même. Sizeof short content.wlen: 4

Quelqu'un peut-il m'expliquer cela ?

Merci d'avance.

EDIT : Merci d'avoir répondu ! J'ai compris maintenant.

3voto

mouviciel Points 36624

Les membres de la structure sont souvent alignés sur des frontières de 4 octets si le compilateur estime que l'accès sera plus pratique de cette façon. Un comportement similaire se produit avec les chars.

Vous pouvez essayer d'optimiser l'empreinte mémoire de votre structure en regroupant les shorts, de sorte que deux shorts consécutifs utilisent un seul mot de 32 bits. N'oubliez pas de vérifier les résultats du compilateur.

2voto

Tal Pressman Points 4120

Selon la norme C, chaque type natif en mémoire doit être aligné sur sa taille, mais ce n'est pas directement lié à votre problème. Ce que vous devriez examiner, c'est l'emballage des structures.

2voto

JJacobsson Points 123

Comme dfa l'a dit, c'est dû à l'alignement. Une "bonne pratique" qui peut aider à réduire la taille de vos structures est d'ordonner ses membres par leur taille individuelle (en fait leur alignement individuel, mais la taille est souvent suffisante) en commençant par le plus grand membre.

Ce n'est pas toujours vrai, mais la plupart du temps.

1voto

Claes Mogren Points 918

Jetez un oeil à pahole, diminutif de Poke-a-Hole. C'est l'un des outils de DWARF2 utilisé pour trouver des trous dans les structures, les trous étant des espaces entre les membres en raison des règles d'alignement, qui pourraient être utilisés pour de nouvelles entrées de structure ou être réorganisés pour réduire la taille.

Pour en savoir plus, consultez le site cet article du LWN par l'auteur du programme, Arnaldo Carvalho de Melo.

Il n'y a pas beaucoup de tutoriels à trouver sur le net, mais cette page wiki au CERN est quelque peu utile.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X