Contents

Capítulo 12 - Operadores de Baixo Nível


botões
botões Conteúdo Capítulo anterior Capítulo seguinte

Vimos em capítulo anterior como os apontadores permitem operar sobre a memória a baixo nível. De igual modo, o C possui outros operadores que atuam ao nível do byte e do bit.

Estes operadores podem 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 operativo).

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 operativo UNIX, foi quase totalmente escrito em C.


Tópicos

setas
setas Up

Operadores bit a bit

Os operadores bit a bit do C estão sumarizados na tabela seguinte:

Tabela operadores
  operador   significado
  &     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  

É necessário conhecer a diferença 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 possuírem 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 na função:

  int bitcount(unsigned char x)
  {
  int count;

  for (count = 0; x != 0; x>>=1)
    if (x & 1)
      count++;
  return count;
  }
setas
setas 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á também servir para a leitura de ficheiros 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;

Neste exemplo 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:

setas
setas Up

Exercícios

  1. Escreva uma função que mostre, em binário, o valor de um unsigned char, passado como argumento.
  2. Escreva uma função setbits(x, p, n, y) que retorne o valor de x com os n bits que começam na posição p de x, iguais aos n bits menos significativos de y. Escreva ainda um programa de teste desta função, que pergunte valores ao utilizador, os passe à função e imprima o resultado em binário, juntamente com os valores primitivos de x e y.
  3. Escreva um programa que inverta os bits de um valor. O programa deverá imprimir em binário o valor original e o valor invertido.
  4. Escreva uma função que rode (rotate) os bits de um determinado valor. Teste a função num programa que mostre o valor original e o valor rodado em binário.
setas
setas Up