Operações com bits na linguagem C
MC404 2o semestre de 2015


Atualizado em 17/08/2015
Prof. Célio

A linguagem C foi criada em 1972 pelos desenvolvedores do sistema Unix (Ken Thompson e Dennis Ritchie) com o objetivo de nela escreverem o sistema operacional Unix (Linux é uma versão moderna do Unix e Ubuntu é uma distribuição popular).

Num sistema operacional operações de Entrada/Saída usam extensivamente manipulação de bits, por isto C dispõe de um conjunto compreensivo de operadores lógicos binários para este fim. Quando o segundo operando de uma operação lógica binária é uma constante ele é comumente chamado de "máscara". No que se segue suporemos que "variavel" foi declarada como "unsigned int": nesse caso o gcc usa 32 bits para armazenar a variavel.

Existe também um operador unário "~" que complementa todos os bits do operando;
Observe que: variavel= ~variavel equivale a: variavel= variavel ^ 0xffffffff

Exercícios

Considere variáveis de 32 bits. Note que bits são numerados da direita para a esquerda de 0 (bit menos "significativo") a 31 (bit "mais significativo").
Faça trechos de programa em C para:
  1. Ligar/desligar o bit k (constante) de uma variável.
  2. Inverter os bits de uma variável sem usar o operador ~.
  3. Fazer o "ou" de uma variável dado um apontador para a mesma, com o valor de outra variável.
  4. Fazer o "and" de uma variável dado um apontador para a mesma, com o valor de outra variável.
  5. Multiplicar por 16 uma variável sem usar o operador de multiplicação *.
  6. Dividir por 16 uma variável sem usar o operador de divisão /.
  7. Ligar/desligar os n bits menos significativos de uma variável sem alterar os outros bits (n = constante (0-31)).Dica: a partir da máscara 0xffffffff (-1), gere uma máscara com os n bits menos sigificativos iguais a 0
  8. Ligar/desligar os n bits mais significativos de uma variável sem alterar os outros bits (n = constante). Dica: - mesma do problema anterior.
  9. Considere o campo de bits de uma variável localizado entre os n bits mais significativos e os n bits menos significativos:
    (i) desligue os bits desse campo sem alterar os outros bits.
    (ii) ligue os bits desse campo sem alterar os outros bits.
    Sugestão: use as duas máscaras dos dois problemas anteriores para gerar a máscara desejada.

Exercícios mais elaborados

Escreva em C as seguintes funções (derivadas de instruções com o mesmo nome nos processadores ARM Cortex M3):
  1. ubfx(unsigned int * dest,unsigned int src, const int sbit, const int nbits) ( ubfx = unsigned bit field extract), com o objetivo de extrair da variavel src um campo de nbits a partir do bit sbit menos significativo (ou seja, incluindo os bits sbit, sbit+1, ...,sbit+nbits-1), e inseri-lo nos nbits menos significativos da variável dest, zerando os bits restantes da mesma.

  2. sbfx(int * dest, int src, const int sbit, const int nbits) (signed bit field extract),
    semelhante ao anterior, porém o bit mais significativo do campo deve ser considerado como um bit de sinal e deve ser propagado para os 32-nbits mais significativos de dest.
    Dica: é possivel escrever as duas funções acima sem usar máscaras, apenas operações de deslocamento!

  3. bfc(unsigned int * dest, const int sbit, const int nbits) (bit field clear):
    zerar os bits sbit a sbit+nbits-1 da variável dest, sem alterar os outros bits da variável
    Sugestão: crie duas máscaras apropriadas: m1=|1111111|sbits 0| e m2=|000000|nbits + sbits 1|. O seu uso deve, então, ficar claro.

  4. bfi(unsigned int * dest, unsigned int src, const int sbit, const int nbits) - bit field insert:
    extrair um campo com os nbits menos significativos da variável src e inseri-lo na variavel dest a partir do bit sbit sem alterar os outros bits de dest Sugestão: utilize o problema anterior para zerar o campo desejado na variável dest e sem usar máscaras gere o campo apropriado a partir da variável src; o resto fica óbvio.