Jim cayó
Estoy escribiendo una aplicación C++ para Windows XP/Vista/7 usando Visual Studio 2008. Algunas de mis estructuras usan un campo de bits, como se muestra en el ejemplo.
typedef struct myStruct_tag
{
BYTE myVar1;
WORD myVar2;
WORD myVar3;
union
{
struct
{
BYTE :1;
BYTE field1 :1;
BYTE field2 :1;
BYTE reserved :5;
} myBitField;
BYTE myVar4;
};
BYTE myVar5;
BYTE myVar6;
} myStruct_t;
¿Qué extremo del campo es el bit más significativo?
C99 estándar 6.7.2.1/10 (énfasis mío):
Una implementación puede asignar cualquier unidad de almacenamiento direccionable lo suficientemente grande como para contener un campo de bits. Si queda suficiente espacio, un campo de bits que sigue inmediatamente a otro campo de bits en una estructura se empaquetará en bits adyacentes de la misma unidad. Si queda espacio insuficiente, la implementación define si un campo de bits que no encaja se coloca en la siguiente unidad o se superpone a las unidades adyacentes. El orden de asignación de campos de bits dentro de una unidad (de orden superior a orden inferior o de orden inferior a orden superior) está definido por la implementación. No se especifica la alineación de la unidad de almacenamiento direccionable.
Por lo tanto, el orden debe estar documentado por la implementación de su compilador.
Sin embargo, gran parte de cómo se implementan los campos de bits están definidos o no especificados en la implementación, por lo que no vale la pena intentar usarlos para modelar campos de bits de hardware, protocolo de conexión o formato de archivo de forma portátil.
Si desea que sus ‘campos de bits’ modelen algo externo a su programa (como las cosas anteriores), use máscaras explícitas, configurando y borrando los bits usando los operadores bit a bit estándar (|
‘&,
~,
-
+10 si pudiera. Su respuesta a esta pregunta es la mejor razón para no usar campos de bits para lo principal que la gente cree que son útiles.
– R.. GitHub DEJA DE AYUDAR A ICE
28 de diciembre de 2010 a las 19:44
-
No me di cuenta de que la gente intenta usarlos de forma portátil, el único uso que he visto es “hablar con el hardware desde mi programa que usa el compilador X”. Y mire todos los millones de preguntas “Hago esto en el compilador X, ¿cómo hago eso en el compilador Y?”.
– Código Abominable
14 de abril de 2015 a las 0:13
-
@CodeAbominator: como ejemplo, he visto campos de bits utilizados para descifrar mensajes de protocolo de red o formatos de archivos binarios. También he visto que parte de ese código no funciona cuando se compila para una plataforma diferente.
– Michael Burr
15 de abril de 2015 a las 7:14
-
Esto es exactamente para lo que se utilizan los campos de bits. Sería útil si un futuro estándar C definiera este comportamiento, pero en el mundo incrustado, los campos de bits y las uniones son necesarios y los programadores y los fabricantes de dispositivos los utilizan en sus archivos de encabezado. Tenga cuidado, consulte la documentación del compilador y no espere que sea portátil. Úselo en código dependiente de hardare de bajo nivel, donde sea necesario especificar un bit en particular y donde el uso de máscaras aumente el tamaño del código, reduzca el rendimiento y no proporcione ningún beneficio (ya que este tipo de código, por definición, no es portátil).
– usuario1582568
8 de noviembre de 2020 a las 18:51
Los documentos del compilador de Visual Studio 2008 indican:
El orden de los datos declarados como campos de bits es de menor a mayor bit
De “Campos de bits de C++”, Referencia del lenguaje C++ de MSDN, versión de Visual Studio 2008
-
Como han señalado otros, los estándares relevantes no especifican esto, y es bueno escribir código compatible con los estándares, pero esta es la respuesta a la pregunta que se hizo, y el lector puede decidir si quiere usar sus poderes para bien o para mal. por genial ;PAGS
– rebanada de rak
23 de febrero de 2017 a las 8:08
Si está preguntando qué bits en myBitField se almacenan en qué bits del byte en la memoria, eso no está definido explícitamente por los estándares C. Tendrás que aprender experimentando. Probablemente valga la pena, si está haciendo algo en lo que realmente importa, usar un enfoque en el que #defina field1
como un valor hexadecimal (por ejemplo, 0x40
o 0x02
) y colócalo donde quieras.
-
Desafortunadamente, las pruebas funcionales de esta parte del código se llevarán al menos semanas, si no meses. (Hay muchas cosas que deben escribirse para probar realmente algo porque ahora estoy en un punto en el que todo lo que queda por escribir es más o menos interdependiente de todo lo demás). Las constantes definidas son una opción, pero preferiría usar campos de bits porque el primero requeriría un lote más lógica en mi código.
– Jim Cayó
28 de diciembre de 2010 a las 16:36
-
Bueno, un experimento rápido debería mostrarle lo que está haciendo el compilador ahora… solo defina la unión como arriba, asigne 0 a
myVar4
luego asigne 1 afield1
e imprimir el valor resultante demyVar4
. Pondría un nombre en el bit no utilizado que ha definido antesfield1
sin embargo, para que el compilador no lo optimice.– Jay Maynard K5ZC
28 de diciembre de 2010 a las 16:58
Nota: Según el estándar, el MSB no está definido. En su plataforma específica, sospecho que
reserved
contiene el MSB pero no estoy seguro.– Billy ONeal
28 de diciembre de 2010 a las 16:24
@Billy: Eso me parece una respuesta.
– Ben Voigt
28 de diciembre de 2010 a las 16:26
Er… Esa es una pregunta bastante extraña. Solo tiene campos de 3 bits en su declaración. 2 de ellos son campos de bits de 1 bit, es decir, no hay problema de “qué extremo” con ellos, ya que solo hay 1 bit allí. El único campo de bits multibit llamado
reserved
, lo que sugiere que no se utiliza en absoluto. Entonces, básicamente, el único campo de bits al que se puede aplicar la pregunta esreserved
. ¿Estás preguntando sobrereserved
¿específicamente? Si no, aclara tu pregunta.– AnT apoya a Rusia
28 de diciembre de 2010 a las 16:26
@Ben: Si hubiera sido positivo sobre qué variable obtendría el MSB, habría sido una respuesta, pero no estoy seguro …
– Billy ONeal
28 de diciembre de 2010 a las 16:27
Esto es importante porque la estructura se usa para definir un paquete para comunicaciones en serie. Los campos de bits deben estar alineados en ambos lados del sistema, del cual, lamentablemente, solo tengo control sobre un lado.
– Jim Cayó
28 de diciembre de 2010 a las 16:30