Campo de bits
Declara un dato miembro de clase con un tamaño explícito, en bits. Miembros de campos de bits adyacentes pueden (o no) ser compactados para compartir y abarcar los bytes individuales.
Una declaración de campo de bits es una declaración de un dato miembro de clase que utiliza el siguiente declarador:
identificador(opcional)atrib(opcional): tamaño | (1) | ||||||||
identificador(opcional)atrib(opcional): tamañoinicializador-con-llaves-o-signo-igual | (2) | (desde C++20) | |||||||
El tipo del campo de bits se introduce mediante la sec-decl-especificador de la sintaxis de declaración.
atrib(C++11) | - | secuencia opcional de cualquier número de atributos |
identificador | - | el nombre del campo de bits que se está declarando. El nombre es opcional: campos de bits sin nombre introducen el número especificado de bits de relleno |
tamaño | - | una expresión constante entera con un valor mayor o igual a cero. Cuando es mayor que cero, éste es el número de bits que este campo de bits ocupará. El valor cero solamente se permite para los campos de bits sin nombre y tiene un significado especial: especifica que el próximo campo de bits en la definición de la clase comenzará en un límite de la unidad de asignación. |
inicializador-con-llaves-o-signo-igual | - | inicializador de miembro por defecto a ser usado con este campo de bits. |
Contenido |
[editar]Explicación
El tipo de un campo de bits solamente puede ser entero o enumerado (que puede estar cualificado cv).
Un campo de bits no puede ser un dato miembro estático.
No hay campo de bits prvalues: la conversión de lvalue a rvalue simepre produce un objeto del tipo subyacente del campo de bits.
El número de bits en un campo de bits establece el límite del rango de valores que puede contener:
#include <iostream>struct S {// campo de tres bits sin signo (unsigned),// los valores permitidos son de 0...7unsignedint b :3;}; int main(){ S s ={6}; ++s.b;// almacenar el valor 7 en el campo de bitsstd::cout<< s.b<<'\n'; ++s.b;// el valor 8 no cabe en este campo de bitsstd::cout<< s.b<<'\n';// formalmente, definido por la implementación, típicamente 0}
Posible salida:
7 0
Normalmente campos de bits múltiples adyacente se empaquetan juntos (aunque este comportamiento lo define la implementación):
#include <iostream> struct S {// normalmente ocupará 2 bytes:// 3 bits: valor de b1// 2 bits: sin uso// 6 bits: valor de b2// 2 bits: valor de b3// 3 bits: sin usounsignedchar b1 :3, :2, b2 :6, b3 :2;}; int main(){std::cout<< sizeof(S)<<'\n';// habitualmente imprime 2}
Posible salida:
2
El campo de bits especial sin nombre de tamaño cero se usa para forzar la división del relleno. Específica que el próximo campo de bits comienza al principio de su unidad se asignación:
#include <iostream> struct S {// normalmente ocupará 2 bytes:// 3 bits: valor de b1// 5 bits: sin uso// 6 bits: valor de b2// 2 bits: valor de b3unsignedchar b1 :3;unsignedchar:0;// comienza un nuevo byteunsignedchar b2 :6;unsignedchar b3 :2;};int main(){std::cout<< sizeof(S)<<'\n';// normalmente imprime 2}
Posible salida:
2
Si el tamaño especificado para el campo de bits es mayor que el tamaño de su tipo, el valor está limitado por el tipo: un std::uint8_t b :1000; todavía contendría valores entra 0 y 255. Los bits extra se convierten en relleno sin uso.
Debido a que los campos de bits no necesariamente comienzan al principio de un byte, no se puede obtener la dirección de un campo de bits. Punteros y referencias no constantes a campos de bits no son posibles. Al inicializar una referencia constante desde un campo de bits, se crea un temporal (su tipo es el tipo del campo de bits), se inicializa la copia con el valor del campo de bits y la referencia se vincula a ese temporal.
No hay inicializadores de miembro por defecto para campos de bits: int b :1=0; y int b :1{0} están mal formados. | (hasta C++20) |
En caso de ambigüedad entre el tamaño del campo de bits y el inicializador de miembro por defecto, se selecciona la secuencia más larga de tókenes que forman un tamaño válido: int a;constint b =0; struct S {// simple casesint x1 :8=42;// Correcto; "= 42" es un inicializador de llaves o igualint x2 :8{42};// Correcto; "{ 42 }" es un inicializador de llaves o igual // ambigüedadesint y1 :true?8: a =42;// Correcto; el inicializador de llaves o igual está ausenteint y2 :true?8: b =42;// ERROR: no se puede asignar a const intint y3 :(true?8: b)=42;// Correcto; "= 42" es un inicializador de llaves o igualint z :1|| new int{0};// Correcto; el inicializador de llaves o igual está ausente}; | (desde C++20) |
[editar]Notas
Las siguientes propiedades de los campos de bits están definidas por la implementación
- El valor que resulta de asignar o inicializar un campo de bits con signo con un valor fuera de rango, o de incrementar un campo de bits con signo superando su rango.
- Todo acerca de los detalles de almacenamiento de los campos de bits en un objeto clase
- Por ejemplo, en algunas plataformas, los campos de bits no abarcan bytes separados, en otras sí.
- También, en algunas plataformas, los campos de bits se empaquetan de izquierda a derecha, en otros de derecha a izquierda.
En el lenguaje de programación C, el ancho de un campo de bits no puede exceder el ancho del tipo subyacente, y los campos de bits int donde no se especifica signed o unsigned, la implementación define si son con o sin signo. Por ejemplo, int b:3; puede tener los rangos de valores 0..7 o -4..3 en C, pero solo se permite el último caso en C++.
[editar]Informe de defectos
Los siguientes informes de defectos de cambio de comportamiento se aplicaron de manera retroactiva a los estándares de C++ publicados anteriormente.
ID | Aplicado a | Comportamiento según lo publicado | Comportamiento correcto |
---|---|---|---|
CWG 324 | C++98 | No se especificó si el valor de retorno de una asignación a un campo de bits es un campo de bits | Se agregaron especificaciones de campo de bits para operadores que pueden devolver l-valores. |
CWG 739 | C++98 | El signo de los campos de bits signed o unsigned estaba definido por la implementación. | Es consistente con los tipos subyacentes. |
CWG 2511 | C++98 | No se permitían las calificaciones-cv en tipos de campo de bits | Los campos de bits pueden tener tipos enumerados. calificados-cv. |
[editar]Referencias
- El estándar C++20 (ISO/IEC 14882:2020):
- 11.4.9 Bit-fields [class.bit]
- El estándar C++17 (ISO/IEC 14882:2017):
- 12.2.4 Bit-fields [class.bit]
- El estándar C++14 (ISO/IEC 14882:2014):
- 9.6 Bit-fields [class.bit]
- El estándar C++11 (ISO/IEC 14882:2011):
- 9.6 Bit-fields [class.bit]
- El estándar C++03 (ISO/IEC 14882:2003):
- 9.6 Bit-fields [class.bit]
- El estándar C++98 (ISO/IEC 14882:1998):
- 9.6 Bit-fields [class.bit]
[editar]Véase también
Implementa un array de bits de longitud constante. (plantilla de clase) | |
Conjunto de bits eficiente en el uso de espacio. (plantilla de clase) | |
Manipulación de bits(C++20) | Utilerías para acceder, manipular y procesar bits individuales y secuencias de bits. |
Documentación de C para Campos de bits |