Pregunta

Estoy trabajando en turbo C en windows donde char toma un byte. Ahora mi problema es con la siguiente unión.

union a
{
 unsigned char c:2;
}b;
void main()
{
printf("%d",sizeof(b));  \\or even sizeof(union a)
}

Este programa está imprimiendo la salida como 2 donde la unión debería tomar solo 1 byte. ¿Por que es esto entonces?

para struct, está bien dar 1 byte pero esta unión funciona de manera inapropiada.

Y una cosa más sobre cómo acceder a estos campos de bits.

scanf("%d",&b.c);  //even scanf("%x",b.c);

no funciona porque no podemos tener una dirección para los bits, así que tenemos que usar otra variable como la siguiente

int x;
scanf("%d",&x);
b.c=x;

¿no podemos evitarlo? ¿hay alguna otra forma?

¿Fue útil?

Solución

Turbo C se basa en un microprocesador 8086 que tiene un límite de palabras de dos bytes . La lectura y escritura atómica generalmente está vinculada a la arquitectura de la CPU, por lo que el compilador agrega algunos bytes de holgura para alinear su estructura de datos.

texto alternativo ??

Llamar a #pragma pack (1) puede desactivarlo, pero no estoy seguro de si funciona en Turbo C.

Otros consejos

Los compiladores pueden agregar relleno a estructuras y uniones, y aunque, lo admito, es un poco sorprendente que el tuyo redondee la unión a un tamaño de dos bytes cuando puedes obtener una estructura de un byte, está perfectamente permitido .

En respuesta a su segunda pregunta: no, no es evitable. Los campos de bits son una optimización de empaquetamiento de estructura y la penalización de rendimiento y conveniencia a pagar es que los miembros de los campos de bits no son direccionables individualmente.

No estoy seguro de dónde encuentra el requisito de que la unión debe ser precisamente del tamaño mínimo. Un objeto debe ser al menos tan grande como sus miembros, pero eso es solo un límite inferior.

No puede tomar la dirección de un campo de bits; ¿Cuál sería su tipo? No puede ser int *. scanf (% d) escribirá sizeof (int) * CHAR_BIT bits en el int * que ingresa. Eso es escribir más de 2 bits, pero no tiene ese espacio.

Hay un párrafo en el estándar que establece que no habrá relleno antes del primer miembro de una estructura. Pero no lo dice explícitamente sobre los sindicatos. La diferencia de tamaño podría venir porque quiere alinear la unión en los límites de 2 bytes, pero como no puede rellenarse antes del primer miembro de una estructura, la estructura tendrá una alineación de un byte. También tenga en cuenta que un sindicato podría tener más miembros con diferentes tipos, lo que podría ampliar la alineación requerida de su sindicato. Podría haber razones para que el compilador les dé al menos 2 bytes de alineación, por ejemplo, para facilitar el código que debe manejarse de acuerdo con la alineación requerida de una unión.

De todos modos, no hay requisito de que su sindicato sea exactamente un byte. Simplemente tiene que tener lugar para todos sus miembros.

Esto es lo que el estándar C tiene que decir sobre su segunda pregunta:

El operando del unario & amp; el operador debe ser una función designador o un valor de l que designa un objeto que no es un campo de bits y no se declara con la clase de almacenamiento de registro especificador.

Entonces, su mejor opción es usar su manera usando int. puede poner llaves alrededor del código, para que la variable temporal se mantenga local:

void func(void) { struct bits f; { int x; scanf("%d", &x); f.bitfield = x; } /* ... */ }

Hay mucha información errónea en las respuestas, por lo que aclararé. Podría ser por una de 2 razones (no estoy familiarizado con el compilador).

  1. La unidad de almacenamiento de campo de bits es 2.

  2. La alineación se fuerza al límite de la palabra (2 bytes).

Dudo que sea el primer caso, ya que es una extensión común tomar la unidad de almacenamiento de campo de bits como el tamaño de la "base" declarada tipo. En este caso, el tipo es char, que siempre tiene un tamaño de 1.

[En estándar, solo puede declarar campos de bits de tipo int o unsigned int y la " unidad de almacenamiento " en el que se agrupan los campos de bits es fijo (generalmente el mismo tamaño que un int). Incluso un campo de bits de un solo bit utilizará una unidad de almacenamiento.]

En el segundo caso, es común que los compiladores de C implementen #pragma pack para permitir el control de la alineación. Sospecho que el empaque predeterminado es 2, en cuyo caso se agregará un byte de pad al final de la unión. La forma de evitar esto es usar:

#pragma pack(1)

También debe usar #pragma pack () después para volver a los valores predeterminados (o incluso mejor usar los argumentos push y pop si su compilador lo admite).

Para todos los que respondieron que dijeron que debe soportar lo que hace el compilador, esto es contrario al espíritu de C. Debería poder usar bitfields para mapear a cualquier tamaño u orden de bits en situaciones donde no tiene control sobre él, como un formato de archivo o mapeo de hardware.

Por supuesto, esto es altamente no portátil ya que diferentes implementaciones tienen diferentes órdenes de bytes, órdenes de que los bits se agreguen a una unidad de almacenamiento de campo de bits (de arriba a abajo), tamaño de las unidades de almacenamiento, alineación predeterminada, etc.

En cuanto a su segunda pregunta, no puedo ver el problema, aunque nunca uso scanf ya que es problemático.

Además del hecho de que '' también puede haber relleno sin nombre al final de una estructura o unión '', el compilador puede colocar un campo de bits en '' cualquier unidad de almacenamiento direccionable lo suficientemente grande como para contener un bit- campo " ;. (ambas citas son del estándar C90; hay una redacción similar, pero diferente, que cumple el estándar C99).

También tenga en cuenta que el estándar dice que un "campo de bits" tendrá un tipo que sea una versión calificada o no calificada de int, unsigned int, o firmado int " ;, por lo que tener un campo de bits en un tipo char no es -estándar.

Debido a que el comportamiento de los campos de bits depende mucho de los detalles de implementación del compilador no especificados (hay varios otros problemas no portátiles con los campos de bits que no he mencionado) usarlos es casi siempre una mala idea. En particular, son una mala idea cuando intenta modelar campos de bits en un formato de archivo, protocolo de red o registro de hardware.


Más información de otra respuesta SO :

  

En general, debe evitar los campos de bits   y usar otras constantes manifiestas   (enumeraciones o lo que sea) con bit explícito   enmascarar y cambiar para acceder a la   'subcampos' en un campo.

     

Aquí hay una razón por la cual los campos de bits deberían   evitarse, no son muy portátiles   entre compiladores incluso para el mismo   plataforma. del estándar C99   (hay una redacción similar en el C90   estándar):

     
    

Una implementación puede asignar cualquier     unidad de almacenamiento direccionable lo suficientemente grande     para sostener un campo de bits. Si hay suficiente espacio     permanece, un campo de bits que inmediatamente     sigue otro campo de bits en un     la estructura se empacará en     bits adyacentes de la misma unidad. Si     queda espacio insuficiente, ya sea     campo de bits que no encaja se pone     en la siguiente unidad o se superpone     unidades adyacentes es     definido por la implementación. El orden de     asignación de campos de bits dentro de una unidad     (orden alta a orden baja o orden baja     de alto orden) es     definido por la implementación. El alineamiento     de la unidad de almacenamiento direccionable es     sin especificar.

  
     

No puede garantizar si un poco   campo 'abarcará' un límite int o   no y no puede especificar si un   bitfield comienza en el extremo inferior de la   int o el extremo superior de int (esto   es independiente de si el   el procesador es big-endian o   little-endian).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top