type fields c

fields - bit type c



Cuándo usar bit-fields en C? (14)

En la pregunta "¿por qué necesitamos usar campos de bits?", En Google descubrí que los campos de bits se utilizan para las banderas. Ahora tengo curiosidad, ¿es la única forma en que se usan prácticamente los campos de bits? ¿Necesitamos usar campos de bits para ahorrar espacio?

Forma de definir el campo de bits del libro:

struct { unsigned int is_keyword : 1; unsigned int is_extern : 1; unsigned int is_static : 1; } flags;

¿Por qué usamos int? ¿Cuánto espacio está ocupado? Estoy confundido por qué estamos usando int, pero no corto o smith más pequeño que int. Como entiendo, solo 1 bit está ocupado en la memoria, pero no el valor entero sin firmar. ¿Es correcto?


¿Por qué usamos int? ¿Cuánto espacio está ocupado?

Una respuesta a esta pregunta que no he mencionado en ninguna de las otras respuestas es que el estándar C garantiza el soporte para int. Específicamente:

Un campo de bits debe tener un tipo que sea una versión calificada o no calificada de _Bool, firmado int, unsigned int, o algún otro tipo definido de implementación.

Es común que los compiladores permitan tipos de campo de bit adicionales, pero no son necesarios. Si realmente te preocupa la portabilidad, int es la mejor opción.


Ahora tengo curiosidad, [son banderas] la única forma en que se usan los campos de bits prácticamente?

No, las banderas no son la única forma en que se usan los campos de bits. También se pueden usar para almacenar valores de más de un bit, aunque las banderas son más comunes. Por ejemplo:

typedef enum { NORTH = 0, EAST = 1, SOUTH = 2, WEST = 3 } directionValues; struct { unsigned int alice_dir : 2; unsigned int bob_dir : 2; } directions;

¿Necesitamos usar campos de bits para ahorrar espacio?

Los campos de bit ahorran espacio. También permiten una manera más fácil de establecer valores que no están alineados por byte. En lugar de cambiar de bit y usar operaciones bit a bit, podemos usar la misma sintaxis que los campos de configuración en una struct . Esto mejora la legibilidad. Con un campo de bits, podrías escribir

directions.bob_dir = SOUTH;

Sin embargo, al hacerlo manualmente, necesitaría escribir algo como:

#define BOB_OFFSET 2 directions &= ~(3<<BOB_OFFSET); // clear Bob''s bits directions |= SOUTH<<BOB_OFFSET;

Esta legibilidad mejorada es sin duda más importante que guardar unos pocos bytes aquí y allá.

¿Por qué usamos int? ¿Cuánto espacio está ocupado?

El espacio de un entero entero está ocupado. Usamos int porque en muchos casos, realmente no importa. Si, por un solo valor, usa 4 bytes en lugar de 1 o 2, su usuario probablemente no lo note. Para algunas plataformas, el tamaño sí importa más y puedes usar otros tipos de datos que ocupan menos espacio ( char , short , uint8_t , etc.).

Como entiendo, solo 1 bit está ocupado en la memoria, pero no el valor entero sin firmar. ¿Es correcto?

No, eso no es correcto. Toda la unsigned int existirá, incluso si solo está utilizando 8 de sus bits.


Los campos de bits se pueden usar para ahorrar espacio en la memoria (pero usar el campo de bits para este propósito es raro). Se usa donde hay restricción de memoria. por ejemplo) durante la programación en sistemas integrados.

Pero esto debería usarse solo si es extremadamente necesario.

Porque no podemos tener la dirección de un campo de bit. Por lo tanto, diríjase al operador y no se puede usar con ellos.


Los campos de bits son mucho más compactos y eso es una ventaja.

Pero no olvides que las estructuras empaquetadas son más lentas que las estructuras normales. También son más difíciles de construir ya que el programador debe definir la cantidad de bits que se utilizarán para cada campo. Esta es una desventaja


Otro lugar donde los bitfields son comunes son los registros de hardware. Si tiene un registro de 32 bits donde cada bit tiene un cierto significado, puede describirlo elegantemente con un campo de bits.

Tal campo de bits es intrínsecamente específico de la plataforma. La portabilidad no importa en este caso.


Para responder a la pregunta original »¿Cuándo utilizar los campos de bits en C?« ... de acuerdo con el libro "Escribir código portátil" de Brian Hook (ISBN 1-59327-056-9, leo la edición alemana ISBN 3-937514-19 -8) y a la experiencia personal:

NUNCA use la expresión idiomática de bitfield del lenguaje C, pero hágalo usted mismo.

Una gran cantidad de detalles de implementación son específicos del compilador, especialmente en combinación con los sindicatos y las cosas no están garantizadas sobre diferentes compiladores y endianess diferente. Si solo hay una pequeña posibilidad de que su código tenga que ser portátil y se compile para diferentes arquitecturas y / o con diferentes compiladores, no lo use.

Tuvimos este caso cuando transferimos el código del pequeño microcontrolador Endian con algún compilador propietario a otro microcontrolador Big Endian con GCC y no fue divertido. : - /

Así es como utilizo flags (orden de bytes de host ;-)) desde entonces:

# define SOME_FLAG (1 << 0) # define SOME_OTHER_FLAG (1 << 1) # define AND_ANOTHER_FLAG (1 << 2) /* test flag */ if ( someint & SOME_FLAG ) { /* do this */ } /* set flag */ someint |= SOME_FLAG; /* clear flag */ someint &= ~SOME_FLAG;

No hay necesidad de una unión con el tipo int y alguna estructura bitfield entonces. Si lee muchos códigos incrustados, las pruebas, los conjuntos y los patrones claros se volverán comunes y los detectará fácilmente en su código.


Para responder las partes de la pregunta, nadie más respondió:

Ints no Shorts

La razón para usar enteros en lugar de cortos, etc. es que en la mayoría de los casos no se ahorrará espacio al hacerlo.

Las computadoras modernas tienen una arquitectura de 32 o 64 bits y se necesitarán 32 o 64 bits, incluso si usa un tipo de almacenamiento más pequeño, como un corto.

Los tipos más pequeños solo son útiles para guardar la memoria si puedes agruparlos (por ejemplo, una matriz corta puede usar menos memoria que una matriz int ya que los cortos se pueden agrupar más juntos en la matriz). Para la mayoría de los casos cuando se utilizan campos de bits, este no es el caso.

Otros usos

Los bitfields se usan más comúnmente para banderas, pero hay otras cosas para las que se usan. Por ejemplo, una forma de representar un tablero de ajedrez utilizado en muchos algoritmos de ajedrez es usar un número entero de 64 bits para representar el tablero (8 * 8 píxeles) y establecer banderas en ese entero para dar la posición de todos los peones blancos. Otro entero muestra todos los peones negros, etc.


Para utilizar el espacio de memoria, podemos usar campos de bits.

Por lo que sé en la programación del mundo real, si lo requerimos, podemos usar booleanos en lugar de declararlo como enteros y luego hacer campo de bits.


Puede usarlos para expandir la cantidad de tipos sin firmar que se ajustan. Ordinaria tendrías solo poderes de 8,16,32,64 ... pero puedes tener todos los poderes con campos de bits.

struct a { unsigned int b : 3 ; } ; struct a w = { 0 } ; while( 1 ) { printf("%u/n" , w.b++ ) ; getchar() ; }


Si también son valores que utilizamos a menudo, no solo ahorramos espacio, sino que también podemos obtener rendimiento ya que no necesitamos contaminar los cachés. Sin embargo, el almacenamiento en caché también es un peligro al utilizar campos de bits, ya que las lecturas y escrituras simultáneas en diferentes bits provocarán una carrera de datos y las actualizaciones en bits completamente separados podrían sobrescribir valores nuevos con valores antiguos.


Un buen uso sería implementar un fragmento para traducir a, y desde, base64 o cualquier estructura de datos no alineada.

struct { unsigned int e1:6; unsigned int e2:6; unsigned int e3:6; unsigned int e4:6; } base64enc; //I don''t know if declaring a 4-byte array will have the same effect. struct { unsigned char d1; unsigned char d2; unsigned char d3; } base64dec; union base64chunk { struct base64enc enc; struct base64dec dec; }; base64chunk b64c; //you can assign 3 characters to b64c.enc, and get 4 0-63 codes from b64dec instantly.

Este ejemplo es un poco ingenuo, ya que base64 también debe considerar la terminación nula (es decir, una cadena que no tiene una longitud l modo que l % 3 es 0). Pero funciona como una muestra de acceso a estructuras de datos no alineadas.

Otro ejemplo: usar esta característica para dividir un encabezado de paquete TCP en sus componentes (u otro encabezado de paquete de protocolo de red del que quiera hablar), aunque es un ejemplo más avanzado y menos para el usuario final. En general: esto es útil con respecto a las aplicaciones internas de PC, SO, controladores y sistemas de codificación.

Otro ejemplo: analizar un número float .

struct _FP32 { unsigned int sign:1; unsigned int exponent:8; unsigned int mantissa:23; } union FP32_t { _FP32 parts; float number; }

(Descargo de responsabilidad: no sé el nombre del archivo / nombre del tipo donde se aplica, pero en C esto se declara en un encabezado; No sé cómo se puede hacer esto para los puntos de 64 bits ya que la mantisa debe tener 52 bits y - en un objetivo de 32 bits tienen 32 bits).

Conclusión: como lo muestran el concepto y estos ejemplos, esta es una función que rara vez se usa porque es principalmente para fines internos, y no para el software día a día.


Un recurso bastante bueno es Bit Fields in C.

La razón básica es reducir el tamaño utilizado. Por ejemplo, si escribes:

struct { unsigned int is_keyword; unsigned int is_extern; unsigned int is_static; } flags;

Utilizará al menos 3 * sizeof(unsigned int) o 12 bytes para representar 3 pequeños indicadores, que solo deberían contener 3 bits.

Entonces, si escribes:

struct { unsigned int is_keyword : 1; unsigned int is_extern : 1; unsigned int is_static : 1; } flags;

Esto usa el mismo espacio que un unsigned int , por lo que 4 bytes. Puede lanzar 32 campos de un bit en la estructura antes de que necesite más espacio.

Esto es algo así como el campo clásico de bit de elaboración casera:

#define IS_KEYWORD 0x01 #define IS_EXTERN 0x02 #define IS_STATIC 0x04 unsigned int flags;

Pero la sintaxis del campo de bits es más limpia, comparar:

if (flags.is_keyword)

en contra:

if (flags & IS_KEYWORD)

y obviamente menos propenso a errores.


Usamos campos de bits en su mayoría (aunque no exclusivamente) para estructuras de banderas: bytes o palabras (o posiblemente cosas más grandes) en las que tratamos de empacar pequeñas (a menudo 2 estados) piezas de información (a menudo relacionadas).

En estos escenarios, los campos de bits se utilizan porque modelan correctamente el problema que estamos solucionando: con lo que estamos tratando no es realmente un número de 8 bits (o 16 bits o 24 bits o 32 bits), sino más bien una colección de 8 (o 16 o 24 o 32) información relacionada pero distinta.

Los problemas que resolvemos usando campos de bits son problemas donde "empaquetar" la información de forma ajustada tiene beneficios mensurables y / o "desempacar" la información no tiene una penalización. Por ejemplo, si expone 1 byte a través de 8 pines y los bits de cada pin pasan por su propio bus que ya está impreso en el tablero para que conduzca exactamente donde se supone que debe hacerlo, entonces un campo de bit es ideal. El beneficio de "empaquetar" los datos es que se pueden enviar de una vez (lo cual es útil si la frecuencia del bus es limitada y nuestra operación depende de la frecuencia de su ejecución), y la penalización de "desempaquetar" los datos es inexistente (o existente, pero vale la pena).

Por otro lado, no usamos campos de bits para booleanos en otros casos, como el control de flujo de programa normal, debido a la forma en que suelen funcionar las arquitecturas de computadora. A las CPU más comunes no les gusta recuperar un bit de la memoria: les gusta buscar bytes o enteros. Tampoco les gusta procesar bits: sus instrucciones a menudo operan en cosas más grandes como enteros, palabras, direcciones de memoria, etc.

Por lo tanto, cuando intenta operar en bits, depende de usted o del compilador (dependiendo del idioma en el que esté escribiendo) escribir operaciones adicionales que realizan enmascaramiento de bits y despojan la estructura de todo menos la información que realmente desea operar en. Si no se obtienen beneficios al "empaquetar" la información (y en la mayoría de los casos, no la hay), el uso de campos de bit para los booleanos solo introduciría sobrecarga y ruido en su código.


¿Por qué necesitamos usar bit-fields?

Cuando desee almacenar algunos datos que pueden almacenarse a menos de un byte, ese tipo de datos se pueden acoplar en una estructura utilizando los campos de Bits. En palabra incrustada, cuando un mundo de 32 bits de cualquier registro tiene un significado diferente para una palabra diferente, entonces también puede usar los archivos de bit para hacerlos más legibles.

Encontré que los campos de bit se usan para banderas. Ahora tengo curiosidad, ¿es la única forma en que se usan prácticamente los campos de bits?

No, esta no es la única forma. Puedes usarlo de otra manera también.

¿Necesitamos usar campos de bits para ahorrar espacio?

Sí.

Como entiendo, solo 1 bit está ocupado en la memoria, pero no el valor entero sin firmar. ¿Es correcto?

NO. La memoria solo puede ser ocupada en múltiples bytes solamente.