Question

Si j'ai une structure C ++, définissant un mot de données 64 bits tel que ..

struct SMyDataWord
{
    int Name : 40;
    int Colour : 24;
};

Qu'est-ce que la syntaxe : 40 signifie ... Cela signifie-t-il que les 40 premiers bits sont réservés au nom et les 24 bits restants à la couleur?

C’est ainsi qu’il semble être utilisé, mais je ne l’ai jamais vu auparavant.

Était-ce utile?

La solution

Les champs de bits, transférés du C. Nom a une largeur de 40 bits, Couleur a une largeur de 24 bits. Votre structure a donc au moins 64 bits. Sur mon système, 64 bits correspondraient à 8 octets.

Autres conseils

Oui, c'est la syntaxe de champs de bits . Ils sont couramment utilisés pour définir des structures mappées sur des registres matériels. Si vous décidez de les utiliser, vous devez garder à l’esprit certaines choses. En premier lieu, vous ne pouvez pas savoir comment le compilateur fait la mise en page, le classement et le remplissage dans les octets constituant les champs. avec le même compilateur mais avec des paramètres d’optimisation différents).

C'est une définition de bitfield.

Nom est un entier capable de stocker exactement 40 bits d'informations. La couleur peut stocker 24 bits.

Ceci est souvent fait pour économiser de l'espace dans les structures souvent nécessaires, ou pour compresser le code jusqu'à une taille facile à gérer pour le CPU (dans votre cas, 64 bits. S'adapte exactement dans un registre de CPU sur une machine 64 bits).

Le code qui accède aux champs de bits s'exécutera cependant un peu plus lentement.

Utilisez-les judicieusement :

  

N'oubliez pas que presque tout sur   champs de bits est la mise en œuvre   dépendant. Par exemple, si les bits   sont stockés de gauche à droite ou   de droite à gauche dépend de la réelle   architecture matérielle. En outre,   chaque compilateur utilise un membre différent   modèle d'alignement, c'est pourquoi la taille   de BillingRec optimisé est de 12   octets plutôt que 9. Vous ne pouvez pas prendre un   adresse de champ de bits, ni pouvez-vous créer   un tableau de bits. Enfin, sur la plupart   implémentations l'utilisation de champs de bits   encourt de la vitesse au-dessus. Par conséquent, quand   vous optimisez votre code, mesurez le   effet d'une certaine optimisation et   ses compromis avant de décider d'utiliser   il.

Ici sizeof montre bien ce qui se passe sous le capot:

#include <iostream>
#include <climits>

struct bc_1 {
   int a : 1;
   int b : 1;
};

struct bc_2 {
   int a : 31;
   int b : 1;
};

struct bc_3 {
   int a : 32;
   int b : 1;
};

struct bc_4 {
   int a : 31;
   int b : 2;
};

struct bc_5 {
   int a : 32;
   int b : 32;
};

struct bc_6 {
   int a : 40;
   int b : 32;
};

struct bc_7 {
   int a : 63;
   int b : 1;
};

int main(int argc, char * argv[]) {
    std::cout << "CHAR_BIT = " << CHAR_BIT;
    std::cout << " => sizeof(int) = " << sizeof(int) << std::endl;

    std::cout << "1,  1:  " << sizeof(struct bc_1) << std::endl;
    std::cout << "31, 1:  " << sizeof(struct bc_2) << std::endl;
    std::cout << "32, 1:  " << sizeof(struct bc_3) << std::endl;
    std::cout << "31, 2:  " << sizeof(struct bc_4) << std::endl;
    std::cout << "32, 32: " << sizeof(struct bc_5) << std::endl;
    std::cout << "40, 32: " << sizeof(struct bc_6) << std::endl;
    std::cout << "63, 1:  " << sizeof(struct bc_7) << std::endl;
}

Ce qui suit dépend de votre compilateur et de votre système d'exploitation, et éventuellement de votre matériel. Sur macOS avec gcc-7 (avec un CHAR_BIT = 8, un int 32 bits (c'est-à-dire la moitié de la longueur de long de 64 bits ) a sizeof (int) = 4) c'est la sortie que je vois:

CHAR_BIT = 8 => sizeof(int) = 4
1,  1:  4
31, 1:  4
32, 1:  8
31, 2:  8
32, 32: 8
40, 32: 12
63, 1:  8

Cela nous dit plusieurs choses: si les deux champs de type int entrent dans un seul int (c'est-à-dire 32 bits dans l'exemple ci-dessus), le compilateur n'alloue qu'un seul La mémoire de int ( bc_1 et bc_2 ). Une fois, un seul int ne peut plus contenir les champs de bits, nous en ajoutons un second ( bc_3 et bc_4 ). Notez que bc_5 est saturé.

Il est intéressant de noter que nous pouvons " sélectionner " plus de bits que permis. Voir bc_6 . Ici g ++ - 7 donne un avertissement:

bitfields.cpp::30:13: warning: width of 'bc_6::a' exceeds its type
     int a : 40;
             ^~

Notez que: clang ++ explique cela plus en détail

bitfields.cpp:30:9: warning: width of bit-field 'a' (40 bits) exceeds the width of its type; value will be truncated to 32 bits [-Wbitfield-width]
    int a : 40;
    ^

Cependant, il semble que sous le capot, le compilateur alloue une autre mémoire à int . Ou à tout le moins, il détermine la taille correcte. Je suppose que le compilateur nous avertit de ne pas accéder à cette mémoire car int a = bc_6 :: a (je parierais que int a n'aurait alors que les 32 premiers bits de champ bc_6 :: a ...). Ceci est confirmé par bc_7 dont la taille totale est celle de deux int , mais le premier champ en couvre la plupart.

Finalement, remplacer int par long dans l'exemple ci-dessus se comporte comme prévu:

CHAR_BIT = 8 => sizeof(long) = 8
1,  1:  8
31, 1:  8
32, 1:  8
31, 2:  8
32, 32: 8
40, 32: 16
63, 1:  8
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top