Pregunta

Si tengo una estructura C ++, definir una palabra de datos de 64 bits como ...

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

¿Qué significa la sintaxis de : 40 ... significa que los primeros 40 bits están reservados para el Nombre y los 24 bits restantes para el Color?

Así es como parece que se está utilizando, pero no lo he visto antes.

¿Fue útil?

Solución

Campos de bits, transferidos desde C. Nombre tiene 40 bits de ancho, Color tiene 24 bits de ancho. Por lo tanto, su estructura tiene al menos 64 bits. En mi sistema, 64 bits serían 8 bytes.

Otros consejos

Sí, esa es la sintaxis de bitfields . Se utilizan comúnmente para definir estructuras que se asignan a registros de hardware. Hay algunas cosas que debe tener en cuenta si decide usarlas, una es que no puede saber cómo el compilador realiza el diseño, el ordenamiento y el relleno en los bytes reales que forman los campos pueden y diferirán entre los compiladores (y quizás con el mismo compilador pero con diferentes configuraciones de optimización, también).

Esa es una definición de campo de bits.

Nombre es un número entero que puede almacenar exactamente 40 bits de información. El color puede almacenar 24 bits.

Esto se hace a menudo para ahorrar algo de espacio en las estructuras que se necesitan con frecuencia, o comprimir el código hasta un tamaño que sea fácil de manejar para la CPU (en su caso, 64 bits. Encaja exactamente en un registro de CPU en una máquina de 64 bits).

El código que accede a los campos de bits se ejecutará un poco más lento.

Utilícelos con prudencia :

  

Recuerda que casi todo sobre   campos de bits es la implementación   dependiente. Por ejemplo, si los bits   se almacenan de izquierda a derecha o   de derecha a izquierda depende de la real   Arquitectura de hardware. Además,   Cada compilador usa un miembro diferente   Modelo de alineación, por lo que el tamaño.   del optimizado BillingRec es 12   bytes en lugar de 9. No puedes tomar un   La dirección del campo de bit ni puedes crear   Una matriz de bits. Finalmente, en la mayoría   Implementaciones del uso de campos de bits.   incurre en la sobrecarga de velocidad. Por lo tanto, cuando   optimizas tu código, mides el   Efecto de una cierta optimización y   sus compensaciones antes de que decida utilizar   it.

Aquí sizeof demuestra muy bien lo que está pasando bajo el capó:

#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;
}

Lo que sigue depende de tu compilador y sistema operativo, y posiblemente de tu hardware. En macOS con gcc-7 (con un CHAR_BIT = 8, un int de 32 bits (es decir, la mitad de un long ) de 32 bits) tiene sizeof (int) = 4) esta es la salida que veo:

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

Esto nos dice varias cosas: si ambos campos de tipo int se ajustan en un solo int (es decir, 32 bits en el ejemplo anterior), el compilador asigna solo una El valor de la memoria de int ( bc_1 y bc_2 ). Una vez, un solo int ya no puede contener los campos de bits, agregamos un segundo ( bc_3 y bc_4 ). Tenga en cuenta que bc_5 está en capacidad.

Curiosamente, podemos " seleccionar " Más bits de los permitidos. Ver bc_6 . Aquí g ++ - 7 da una advertencia:

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

Tenga en cuenta que: clang ++ explica esto con mayor detalle

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;
    ^

Sin embargo, parece que bajo el capó, el compilador asigna el valor de la memoria de otro int . O al menos, determina el tamaño correcto. Supongo que el compilador nos advierte que no accedamos a esta memoria ya que int a = bc_6 :: a (apostaría que int a solo tendría los primeros 32 bits de campo bc_6 :: a ...). Esto está confirmado por bc_7 cuyo tamaño total es el de dos int s, pero el primer campo cubre la mayoría de ellos.

Finalmente, reemplazar int por long en el ejemplo anterior se comporta como se esperaba:

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
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top