2017-10-14 4 views
2

Je sais que dans C, l'ordre des membres struct est l'ordre dans lequel ils sont déclarés plus (habituellement, sauf indication contraire) un remplissage peut se produire, menant aux deux premières structures que j'ai créées avec leur taille respective:Membres de la structure ordonnant des avantages dans C

struct MyStructV1 
{ 
    int a; 
    char c; 
    int b; 
}; 

printf("size of MyStructV1 is:%lu \n",sizeof(struct MyStructV1)); // prints 12 

struct MyStructV1Packed 
{ 
    int a; 
    char c; 
    int b; 
}__attribute__((__packed__));; 

printf("size of MyStructV1Packed is:%lu \n",sizeof(struct MyStructV1Packed)); // prints 9 

Jusqu'ici tout va bien.

Ma question est donc de savoir si la déclaration suivante de la version «déballée» de MyStructV2 présente des avantages/avantages par rapport à la première version de MyStructV1?

struct MyStructV2 
{ 
    int a; 
    int b; 
    char c; 
}; 

printf("size of MyStructV2 is:%lu \n",sizeof(struct MyStructV2)); // prints 12 as well 

Notez que maintenant l'ordre des membres a des changements (b est déclaré avant c).

Je fais référence à l'accès mémoire "coûts" ou des cycles doivent être effectués afin de lire/écrire les membres struct et/ou d'autres considérations qui sont pertinentes?

Est-ce dépendant du compilateur/de l'architecture (le cas échéant)?

Cheers,

Guy.

+2

La plupart du temps, il n'a pas d'importance du tout. Vous pourriez vouloir mettre des champs plus larges avant les plus courts. Bien sûr, cela dépend de l'architecture et de l'ABI –

+1

Il dépend beaucoup du compilateur. Une très bonne règle à suivre est de ne pas s'inquiéter des structures d'emballage, sauf si vous avez une raison spécifique de l'architecture et du compilateur pour le faire et savoir exactement ce que c'est. Sinon, il vaut mieux laisser le compilateur le gérer et insérer un octet ou deux de remplissage à sa guise. –

Répondre

4

Il devrait y avoir peu ou pas de différence entre la première et la dernière version. Dans les deux structures, les membres int sont alignés sur les limites des mots, ce qui permet de les lire efficacement dans la mémoire. La seule différence entre eux est que le rembourrage est entre c et b en MyStructV1, et à la fin de la structure en MyStructV2. Mais il n'y a pas de frais généraux d'exécution en raison du rembourrage; L'accès aux membres de la structure se fait simplement en ajoutant un décalage connu à l'adresse du début de la structure. En MyStructV1 le décalage de b est 8, en MyStructV2 c'est 4.

+3

Ce n'est pas 100% la vérité. Surtout si nous considérons l'emballage de la structure. Emballer sur de nombreuses plates-formes implique l'accès par octet, et il peut même empêcher le programme de fonctionner. Exemple: mot requis périphérique ou accès demi-mot mais la structure est compressée et elle est accessible par octet.L'emballage est surutilisé par les débutants, et doit être utilisé avec précaution. –

+0

@ PeterJ_01 La question portait sur la comparaison des deux structures qui n'utilisent pas d'emballage. Vous avez raison de dire que l'emballage peut produire des hits de performance. – Barmar

1

Si char est plus petit que int (c'est généralement le cas), la structure MyStructV1 peut être plus petite que MyStructV2.

En fonction de l'environnement (architecture et options du compilateur), struct MyStructV1 peut envelopper un pad ou peut désaligner b. En fonction de l'architecture, si b est désaligné, le chargement peut nécessiter plus d'horloge CPU.

En outre, en fonction de l'architecture, la lecture d'un peut charger quelque chose de plus pour être immédiatement disponible, s'il y a des paddings, ce bénéfice est réduit ou perdu.

+0

Très très pauvre et réponse imprécise. OMI, vous devriez le supprimer –

+0

À mon humble avis, il s'agit d'une courte réponse correcte et j'espère que c'est utile à quelqu'un. De toute façon si vous avez une opinion différente s'il vous plaît élaborer. –

0

Cela est plus intéressant et, bien sûr, les questions de commande.

struct aaa1{ 
    char a; 
    char a1; 
    int b; 
}; 

struct aaa2{ 
    char a; 
    char a1; 
    char a2; 
    int b; 
}; 

struct aaa3{ 
    char a; 
    char a1; 
    char a2; 
    char a3; 
    int b; 
}; 

struct aaa4{ 
    char a1; 
    char a2; 
    char a3; 
    int b; 
    char a; 
}; 

int main(void) { 

struct aaa5{ 
    char a; 
    int b; 
    char a1; 
}; 


    printf("%zu %zu %zu %zu %zu %zu\n", sizeof(struct aaa), sizeof(struct aaa1), sizeof(struct aaa2), sizeof(struct aaa3), sizeof(struct aaa4), sizeof(struct aaa5)); 

Sortie: 8 8 8 8 12 12