Capítulo 12 - Operadores de Baixo Nível


Conteúdo Capítulo anterior Capítulo seguinte
Vimos num capítulo anterior como os apontadores nos podem permitir operar sobre a memória, a baixo nível.  No entanto o C possui outros operadores que actuam ao nível do byte e do bit.  Estes operadores poderão ser muito úteis em certos programas que necessitam de controlar de perto o hardware, como por exemplo na programação de sistema (ao nível do sistema operacional).

A combinação dos apontadores e operadores a nível do bit, faz do C uma linguagem capaz de substituir o assembly nas aplicações que dele necessitavam.  Como já se referiu, o sistema operacional UNIX, foi quase totalmente escrito em C.


Tópicos



Operadores bit a bit

Os operadores bit a bit do C estão sumarizados na tabela seguinte:
 
& AND bit a bit
| OR bit a bit
^ XOR bit a bit
~ NOT (inversão) bit a bit
  <<    deslocamento (shift) para a esquerda 
>> deslocamento (shift) para a direita
Uma confusão frequente, que é necessário evitar, é a que existe entre o operador & (AND bit a bit) e o operador && (AND lógico entre duas condições cujo resultado é um dos dois valores booleanos true ou false).  O mesmo acontece com os operadores | e ||.

O operador ~ é um operador unário, i. e., opera apenas sobre um operando que terá de ser colocado à sua direita.

Os operadores de shift executam o deslocamento do operando colocado à sua esquerda, um número de posições indicado pelo operando da direita.  Este último operando terá obrigatoriamente de ser um inteiro positivo.  No deslocamento para a esquerda (<<) as posições que ficam livres são ocupadas com bits em 0.  No deslocamento para a direita (>>) as posições livres são ocupadas com bits em 0, se a quantidade deslocada for sem sinal (unsigned), ou com bits idênticos ao mais significativo, se as quantidades deslocadas possuirem sinal (signed).

Por exemplo,  x << 2,  desloca a representação binária do valor contido em x, duas posições (bits) para a esquerda.

Se x contiver o valor binário 00000010 (2 em decimal) então:  x << 2  faz com que x passe a conter o valor 00001000 (8 em decimal), e x >> 2 faz com que x passe a conter o valor 00000000 (0 em decimal).

Assim, cada posição deslocada para a esquerda corresponde a uma multiplicação por 2, e cada posição deslocada para a direita corresponde a uma divisão por 2.  Geralmente as operações de shift são bastante mais rápidas que as correspondentes operações de multiplicação e divisão.

Para ilustrar alguns destes operadores apresenta-se a seguinte função, capaz de contar o número de bits em 1 contidos num valor de 8 bits (unsigned char), passado como argumento à função:

int bitcount(unsigned char x)
{
    int count;

    for (count = 0; x != 0; x>>=1)
        if (x & 1)
            count++;
    return count;
}

Up

Campos de bits

Os campos de bits (bitfields), permitem o empacotamento de vários valores numa palavra de memória (16 ou 32 bits).  A aplicação principal é poder trabalhar com valores distintos empacotados num registo de hardware (p. ex. posições de I/O de controlo de alguns periféricos).  Poderá servir também para a leitura de arquivos contendo representações não standard (p. ex. inteiros de 9 bits).

Este empacotamento é feito em C através da declaração de uma estrutura, onde a seguir à definição de cada campo se acrescenta o tamanho, em bits, que o mesmo ocupa numa palavra de memória.

Por exemplo:

struct packed_struct {
    unsigned int fl1 : 1;
    unsigned int fl2 : 1;
    unsigned int fl3 : 1;
    unsigned int type : 4;
    unsigned int funny_int : 9;
} pack;
Aqui a variável pack ocupa um total de 16 bits (1 palavra) e contém 5 campos: 3 flags de 1 bit, um campo type de 4 bits (podendo tomar valores de 0 a 15), e um inteiro não standard de 9 bits (valores de 0 a 511).

O acesso aos vários campos faz-se da forma habitual:  o acesso ao campo type denota-se pack.type.

Notas:

Up

Exercícios

Veja aqui os exercícios 

Up

Veja aqui exemplos de exercicios anteriores 



[REV 06/2001]
Up