Quelle est la signification de «__attribute __ ((emballé, aligné (4)))»

122

C'est le langage C. Il est écrit que:

typedef struct __attribute__((packed, aligned(4))) Ball {
    float2 delta;
    float2 position;
    //float3 color;
    float size;
    //int arcID;
    //float arcStr;
} Ball_t;
Ball_t *balls;

Veuillez me dire quelle en est la signification et comment utiliser ce mot-clé.

Aaron Lee
la source
4
C'est un "attribut de type" .. (J'ai trouvé ceci avec "l'attribut C emballé" dans Google. Sûrement d'autres peuvent au moins faire aussi bien!)
1
Voir cette question - mais avec aligned(4)vous n'avez probablement pas grand-chose à craindre.
Keith Thompson

Réponses:

157

Avant de répondre, j'aimerais vous donner quelques données du Wiki


L'alignement de la structure des données est la manière dont les données sont organisées et accessibles dans la mémoire de l'ordinateur. Il se compose de deux problèmes distincts mais liés: l'alignement des données et le remplissage de la structure des données .

Lorsqu'un ordinateur moderne lit ou écrit sur une adresse mémoire, il le fera par blocs de la taille d'un mot (par exemple, des blocs de 4 octets sur un système 32 bits). L'alignement des données signifie placer les données à un décalage de mémoire égal à un certain multiple de la taille du mot, ce qui augmente les performances du système en raison de la façon dont le processeur 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 de la suivante, qui est le remplissage de la structure de données .


gcc fournit des fonctionnalités pour désactiver le remplissage de structure. c'est-à-dire pour éviter ces octets sans signification dans certains cas. Considérez la structure suivante:

typedef struct
{
     char Data1;
     int Data2;
     unsigned short Data3;
     char Data4;

}sSampleStruct;

sizeof(sSampleStruct)sera 12 au lieu de 8. En raison du rembourrage de la structure. Par défaut, dans X86, les structures seront complétées à un alignement sur 4 octets:

typedef struct
{
     char Data1;
     //3-Bytes Added here.
     int Data2;
     unsigned short Data3;
     char Data4;
     //1-byte Added here.

}sSampleStruct;

Nous pouvons utiliser __attribute__((packed, aligned(X)))pour insister sur un rembourrage de taille particulière (X). X doit être une puissance de deux. Référez-vous ici

typedef struct
{
     char Data1;
     int Data2;
     unsigned short Data3;
     char Data4;

}__attribute__((packed, aligned(1))) sSampleStruct;  

donc l'attribut gcc spécifié ci-dessus ne permet pas le remplissage de la structure. donc la taille sera de 8 octets.

Si vous souhaitez faire de même pour toutes les structures, nous pouvons simplement pousser la valeur d'alignement à empiler en utilisant #pragma

#pragma pack(push, 1)

//Structure 1
......

//Structure 2
......

#pragma pack(pop)
Jeyaram
la source
6
Si la mémoire stocke les données en blocs de 4 octets, pourquoi n'ajoute-t-elle pas 2 octets de remplissage au short non signé (sa longueur de 2 octets)? ou le compilateur ajoute simplement des octets de remplissage aux 1er et dernier membres de la structure? pouvez-vous s'il vous plaît clarifier.
Utilisateur
5
@User Plz se réfère également à cela. Si vous n'êtes toujours pas clair, veuillez venir chercher de l'aide stackoverflow.com/questions/11772553/…
Jeyaram
Quiconque a dit que ces octets de remplissage sont dénués de sens ne sait pas que l'accès aux données mal aligné est une bizarrerie de l'architecture x86. Ces octets sont nécessaires pour éviter les exceptions lorsque le processeur tente de charger - disons un entier - des données qui chevauchent sa limite d'alignement naturel.
Tanveer Badar
86
  • packedsignifie qu'il utilisera le plus petit espace possible pour struct Ball- c'est-à-dire qu'il entassera les champs ensemble sans remplissage
  • alignedsignifie que chacun struct Ballcommencera sur une limite de 4 octets - c'est-à-dire que pour tout struct Ball, son adresse peut être divisée par 4

Ce sont des extensions GCC, qui ne font partie d'aucun standard C.

cnicutar
la source
17

L'attribut packedsignifie que le compilateur n'ajoutera pas de remplissage entre les champs du struct. Le remplissage est généralement utilisé pour aligner les champs sur leur taille naturelle, car certaines architectures imposent des pénalités pour un accès non aligné ou ne le permettent pas du tout.

aligned(4) signifie que la structure doit être alignée sur une adresse divisible par 4.

Julian Stecklina
la source