Muitas vezes a informação que queremos armazenar é muito menor que um int de 32 bits, por exemplo usar uma variavel int para armazenar um dado booleano. Isso é um enorme desperdício de espaço.
Entretanto podemos combinar um int com uma struct e obter um código muito elegante, que vai economizar memória e de quebra trás algumas vantagens, veja o exemplo:
union control { unsigned int flag; struct f { unsigned int id:16; unsigned int isRootWindow:1; unsigned int widgetType:8; unsigned int mouseIn:1; unsigned int pixelSize:3; unsigned int reserved:2; } f; } control;
Note que declaramos uma variável unsigned int chamada flag no mesmo nível que a struct f. O union vai “unir” flag e f fazendo com que as duas variáveis tenham o mesmo endereço na memória.
Mas ai vem o truque, note na declaração dos membros da struct f nos definimos o comprimento em bits de cada um colocando no final da declaração “:n” onde n é o numero em bits.
Por exemplo: “:16″ em id faz com que ela tenha 16 bits de comprimento e colocar :1 em mouseIn faz com que ela tenha apenas um bit de comprimento.
Como a struct f e a int flag tem exatamente 32 bits de tamanho as duas combinam perfeitamente.
Como usar:
Podemos acessar cada membros individualmente como nos exemplos:
… ptr->control.f.id++; …
ou
… if (ptr->control.f.mouseIn) …
Ou podemos acessar todos de uma só vez via flag:
… ptr->control.flag = 0;
Vantagens:
Otimiza o uso da memória.
É um meio mais fácil de acessar dados booleanos que se usarmos o modo antigo usando AND, XOR,etc.
Como as informações ficam mais próximas geralmente o uso de memória cache é melhora.
Desvamtagens:
Depende da plataforma, você pode ter que ajustar seu código para ele rodar corretamente em plataformas diferentes da original.