martes, 2 de agosto de 2011

Curso de programación: Capítulo 6. Campos de bits. BitFields


Hola  a todos,

Una de las ventajas de la programación respecto de otras ocupaciones es que es muy raro que haya un dia que no hayas aprendido algo nuevo, lleves 1 semana programando o lleves 15 años.

Mi caso es el segundo y no me avergüenzo de decir que hoy he descubierto (o redescubierto ya que lo más posible es que lo hubiera olvidado) los campos de bits, también conocidos como Bitfields. Un campo de bits, en C, es una manera sencilla y elegante de agrupar variables que ocupan pocos bits (tipicamente flags) en una sola variable, cosa que hace que ocupen menos espacio y el código esté más ordenado.

La forma de implementar los campos de bits es sencilla, aquí teneis un ejemplo:

typedef struct
{
       unsigned char alto:1;
       unsigned char medio:1,
       unsigned char bajo:1;
}Flags;

Para acceder a cada una de las variables seria tan sencillo como el siguiente ejemplo:
Flags f;

if(f.medio)
{
     f.alto = 1;

     f.bajo = 0;
}


La estructura flags ocupa 1 byte  (8 bits), pero internamente tiene 3 variables que ocupan en total 3 bits (es decir, podriamos poner 5 variables sin ocupar más espacio). De no usar los bitfields estariamos gastando 3 bytes, 1 byte para cada flag.

Esto se puede complicar un poco más usando variables que gastan más de un bit, como en el siguiente ejemplo:

typedef struct
{
      unsigned char vel:3;  //podrá tomar valores del 0 al 7
      unsigned char pos:3; //podrá tomar valores del 0 a l 7
     unsigned char hitted:1;
     unsigned char shooting:1;
}Container;

En total la estructura container ocupará 1 byte cuando deberia estar ocupando 4 bytes, y todo esto sin tocar nada de la gestión del código.

Si queremos , podemos todavía complicarlo más poniendo nuevos tipos de datos:
typedef struct
{
         unsinged int a:15;
         unsigned int b:15;
         unsigned char c:1;
        unsigned char d:1;
}Multi;

Una mente avispada diria que la estructura Multi deberia ocupar 32 bits, ergo, 4 bytes, pero.... se ha de tener en cuenta que este sistema agrupa según tipo de variable, es decir, los dos ints irian juntos, gastando 32 bits (usados solo 30) mientras que c y d se agruparian en un solo char usando 2 bits (y gastando 1 byte, claro está). Es decir, la estructura Multi ocuparia 5 bytes.

En cambio, podemos hacer una estructura identica, simplemente cambiando los char por int...

typedef struct
{
          unsinged int a:15;
         unsigned int b:15;
         unsigned int c:1;
        unsigned int d:1;}Multi2;

Y esta estructura si que ocuparia solamente 4 bytes(32 bits).

Que aplicación tiene???

1. Generar un código limpio para trabajar con máscaras de bits. Si nuestra aplicación trabaja a nivel de bits, los que tengan que mantener el proyecto agradecerán que se use bitfields en vez de máscaras raw.
2. Mejor aprovechamiento del espacio en memoria. Hoy dia no acostumbra a ser un problema pero siempre hay casos en que ocupar 8 veces menos memoria puede resultar útil :D
3. Facilidad de programar aplicaciones que trabajen con hardware. En muchas ocasiones el hardware (sobtretodo el antiguo) se comunica con el PC mediante un protocolo basado en bytes. Cada uno de eso bits dentro de los bytes tiene un significado concreto, y usar bitfields ayuda a ordenar las estructuras y el código.

Inconvenientes??
Hay ciertas operaciones que no se le pueden hacer a un campo de bits (tranquilos, si lo probais el compilador os informará de ello muy educamente :D ) tales como un sizeof, vectores o usar & para obtener el puntero a esa variable, adicionalmente se ha de tener cuidado por que no todos los compiladores trabajan de la misma manera con los campos de bits así que puede haber algún problema de no portabilidad.

Espero que os haya gustado y que hayais aprendido

Nos vemos
LordPakusBlog

0 comentarios :

Publicar un comentario

Entradas populares