Bit-field
Déclare un membre de données de classe avec une taille explicite, en bits. Les membres de champs de bits adjacents peuvent (ou non) être regroupés pour partager et chevaucher les octets individuels.
Une déclaration de champ de bits est une déclaration de membre de données de classe qui utilise le déclarateur suivant :
identifiant
(optionnel)
attr
(optionnel)
:
taille
|
(1) | ||||||||
identifiant
(optionnel)
attr
(optionnel)
:
taille
initialiseur-accolade-ou-égal
|
(2) | (depuis C++20) | |||||||
Le type du champ de bits est introduit par la decl-specifier-seq de la syntaxe de déclaration .
| attr | - | (since C++11) séquence d'un nombre quelconque d' attributes |
| identifier | - | le nom du champ de bits qui est déclaré. Le nom est optionnel : les champs de bits sans nom introduisent le nombre spécifié de padding bits . |
| size | - | une integral constant expression avec une valeur supérieure ou égale à zéro. Lorsqu'elle est supérieure à zéro, c'est le nombre de bits que ce champ de bits occupera. La valeur zéro est uniquement autorisée pour les champs de bits sans nom et a une signification spéciale . |
| brace-or-equal-initializer | - | default member initializer à utiliser avec ce champ de bits |
Table des matières |
Explication
Le type d'un champ de bits ne peut être qu'intégral (y compris bool ) ou un type énumération (éventuellement qualifié cv), un champ de bits sans nom ne peut pas être déclaré avec un type qualifié cv.
Un champ de bits ne peut pas être un membre de données statique .
Il n'existe pas de prvalues pour les champs de bits : la conversion lvalue-to-rvalue produit toujours un objet du type sous-jacent du champ de bits.
Le nombre de bits dans un champ de bits fixe la limite de la plage de valeurs qu'il peut contenir :
#include <iostream> struct S { // champ non signé de trois bits, les valeurs autorisées sont 0...7 unsigned int b : 3; }; int main() { S s = {6}; ++s.b; // stocke la valeur 7 dans le champ de bits std::cout << s.b << '\n'; ++s.b; // la valeur 8 ne tient pas dans ce champ de bits std::cout << s.b << '\n'; // formellement défini par l'implémentation, typiquement 0 }
Sortie possible :
7 0
Plusieurs champs de bits adjacents sont généralement regroupés ensemble (bien que ce comportement soit défini par l'implémentation) :
#include <bit> #include <cstdint> #include <iostream> struct S { // occupe généralement 2 octets : unsigned char b1 : 3; // les 3 premiers bits (dans le 1er octet) sont b1 unsigned char : 2; // les 2 bits suivants (dans le 1er octet) sont bloqués comme inutilisés unsigned char b2 : 6; // 6 bits pour b2 - ne tient pas dans le 1er octet => commence un 2ème unsigned char b3 : 2; // 2 bits pour b3 - bits suivants (et finaux) dans le 2ème octet }; int main() { std::cout << sizeof(S) << '\n'; // affiche généralement 2 S s; // définir des valeurs de champs distinctes s.b1 = 0b111; s.b2 = 0b101111; s.b3 = 0b11; // afficher la disposition des champs dans S auto i = std::bit_cast<std::uint16_t>(s); // affiche généralement 1110000011110111 // décomposition : └┬┘├┘└┬┘└─┬──┘└┤ // b1 u a b2 b3 // où « u » marque les bits inutilisés :2 spécifiés dans la structure, et // « a » marque le remplissage ajouté par le compilateur pour aligner le champ suivant sur un octet. // L'alignement sur octet se produit car le type de b2 est déclaré unsigned char ; // si b2 était déclaré uint16_t, il n'y aurait pas de « a », b2 serait adjacent à « u ». for (auto b = i; b; b >>= 1) // afficher LSB en premier std::cout << (b & 1); std::cout << '\n'; }
Sortie possible :
2 1110000011110111
Le champ de bits sans nom spécial de taille zéro peut être forcé à interrompre le remplissage. Il spécifie que le prochain champ de bits commence au début de son unité d'allocation :
#include <iostream> struct S { // occupera généralement 2 octets : // 3 bits : valeur de b1 // 5 bits : non utilisés // 2 bits : valeur de b2 // 6 bits : non utilisés unsigned char b1 : 3; unsigned char :0; // commencer un nouvel octet unsigned char b2 : 2; }; int main() { std::cout << sizeof(S) << '\n'; // affiche généralement 2 // afficherait généralement 1 sans // la rupture de remplissage à la ligne 11 }
Sortie possible :
2
Si la taille spécifiée du champ de bits est supérieure à la taille de son type, la valeur est limitée par le type : un
std::
uint8_t
b
:
1000
;
contiendrait toujours des valeurs dans l'intervalle
[
0
,
255
]
. Les bits supplémentaires sont des
bits de remplissage
.
Parce que les champs de bits ne commencent pas nécessairement au début d'un octet, l'adresse d'un champ de bits ne peut pas être prise. Les pointeurs et les références non constantes vers les champs de bits ne sont pas possibles. Lors de l'initialisation d'une référence const à partir d'un champ de bits, un temporaire est créé (son type est le type du champ de bits), initialisé par copie avec la valeur du champ de bits, et la référence est liée à ce temporaire.
|
Il n'y a pas de initialiseurs par défaut des membres pour les champs de bits : int b : 1 = 0 ; et int b : 1 { 0 } sont mal formés. |
(jusqu'en C++20) |
|
En cas d'ambiguïté entre la taille du champ de bits et l'initialiseur par défaut du membre, la plus longue séquence de tokens formant une taille valide est choisie : int a; const int b = 0; struct S { // cas simples int x1 : 8 = 42; // OK; "= 42" est un brace-or-equal-initializer int x2 : 8 {42}; // OK; "{42}" est un brace-or-equal-initializer // ambiguïtés int y1 : true ? 8 : a = 42; // OK; brace-or-equal-initializer est absent int y2 : true ? 8 : b = 42; // erreur: ne peut pas assigner à const int int y3 : (true ? 8 : b) = 42; // OK; "= 42" est un brace-or-equal-initializer int z : 1 || new int{0}; // OK; brace-or-equal-initializer est absent }; |
(depuis C++20) |
Notes
Les propriétés suivantes des champs de bits sont définies par l'implémentation :
- La valeur qui résulte de l'assignation ou de l'initialisation d'un champ de bits signé avec une valeur hors plage, ou de l'incrémentation d'un champ de bits signé au-delà de sa plage.
- Tout ce qui concerne les détails réels d'allocation des champs de bits dans l'objet classe.
-
- Par exemple, sur certaines plateformes, les champs de bits ne chevauchent pas les octets, tandis que sur d'autres, ils le font.
- De plus, sur certaines plateformes, les champs de bits sont regroupés de gauche à droite, sur d'autres de droite à gauche.
Dans le langage de programmation C, la largeur d'un champ de bits ne peut pas dépasser la largeur du type sous-jacent, et le fait que les champs de bits
int
qui ne sont pas explicitement
signed
ou
unsigned
soient signés ou non est défini par l'implémentation. Par exemple,
int
b
:
3
;
peut avoir la plage de valeurs
[
0
,
7
]
ou
[
-
4
,
3
]
en C, mais seul ce dernier choix est autorisé en C++.
Rapports de défauts
Les rapports de défauts modifiant le comportement suivants ont été appliqués rétroactivement aux normes C++ précédemment publiées.
| DR | Appliqué à | Comportement tel que publié | Comportement correct |
|---|---|---|---|
| CWG 324 | C++98 |
il n'était pas spécifié si la valeur de retour
d'une assignation à un champ de bits est un champ de bits |
ajout des spécifications de champ de bits pour
les opérateurs pouvant retourner des lvalues |
| CWG 739 | C++98 |
le signe des champs de bits qui ne sont ni déclarés
signed ni unsigned était défini par l'implémentation |
cohérent avec les types sous-jacents |
| CWG 2229 | C++98 | les champs de bits anonymes pouvaient être déclarés avec un type qualifié cv | interdit |
| CWG 2511 | C++98 | les qualifications cv n'étaient pas autorisées dans les types de champs de bits |
les champs de bits peuvent avoir des types énumération
qualifiés cv |
Références
- Norme C++23 (ISO/IEC 14882:2024) :
-
- 11.4.10 Champs de bits [class.bit]
- Norme C++20 (ISO/CEI 14882:2020) :
-
- 11.4.9 Champs de bits [class.bit]
- Norme C++17 (ISO/CEI 14882:2017) :
-
- 12.2.4 Champs de bits [class.bit]
- Norme C++14 (ISO/CEI 14882:2014) :
-
- 9.6 Champs de bits [class.bit]
- Norme C++11 (ISO/IEC 14882:2011) :
-
- 9.6 Champs de bits [class.bit]
- Norme C++03 (ISO/IEC 14882:2003) :
-
- 9.6 Champs de bits [class.bit]
- Norme C++98 (ISO/CEI 14882:1998) :
-
- 9.6 Champs de bits [class.bit]
Voir aussi
|
implémente un tableau de bits de longueur constante
(class template) |
|
|
bitset dynamique optimisé en espace
(class template specialization) |
|
| Bit manipulation (C++20) | utilitaires pour accéder, manipuler et traiter des bits individuels et des séquences de bits |
|
C documentation
pour
Bit-fields
|
|