11/10/12 Página de Evy Salcedo Física Computacional FSC5705 Súmula Aulas Lista Conc. Freq. Outros Ensino Operações em nível de bits O grande poder que o C dá ao programador fica explícito nos operadores de controle de bits. Os operadores a seguir atuam sobre variáveis do tipo unsigned char, unsigned short, unsigned int, unsigned long, ou seja, variáveis que possam representar inteiros sem sinal. O operadores de controle de bit são &, |, ^, <<, >> e ~ os quais são e, o, o exclusivo, deslocamento à direita, deslocamento a esquerda e complemento 1 (o qual é um operador unário), respetivamente. O operador & é tal que: operação resultado operação resultado operação resultado 1&1 1 1|1 1 1^1 0 1&0 0 1|0 1 1^0 1 0&1 0 0|1 1 0^1 1 0&0 0 0|0 0 0^0 0 operação resultado ~1 0 ~0 1 Como exemplo consideremos o seguinte número binário 1 0 1 1 0 0 1 1. Esse é um número com 8 bit e representa o número 179 em decimal, vejamos N. Binario → 1 0 1 1 0 0 1 ∗ ∗ ∗ ∗ ∗ ∗ ∗ 7 2 Fator de conversao → Resultado → 128 + N. decimal → 179 6 2 0 + 5 2 32 + 4 2 16 + 3 2 0 + 2 2 0 + 1 2 2 1 ∗ 2 0 1 Esse mesmo número decimal representa a letra que é o 3 quando é elevado ao cubo um numero. Par poder ver isso temos que ajustar nosso terminal para que imprima caráteres representados por 8 bits, isto é colocar no formato iso 8859-15. Para fazer isso clicamos no terminal (parte preta) com o botão direito do mouse e depois clicamos com o botão esquerdo do mouse em Editar o perfil atual ... o que abre uma janela. /media/ext4_evy/Ensino/UFSC/Ano2012/IIsemestre/public_html/…/aula110.html 1/7 11/10/12 Página de Evy Salcedo Nessa janela clicamos na aba Avançado. Na última linha dessa janela que é sobre codificação clicamos em Selecionar, isso abre uma outra janela onde clicamos em Oeste Europeo, isso por sua vez abre uma última janelinha onde escolhemos ISO 8859-15. Colocado na codificação adequada, passamos a testar nosso operadores bit a bit. Mostramo anteriormente que o número binário 1 0 1 1 0 0 1 1 é o número 179 que no padrão ISO 885915 (ASCII) representa o cubo (3). Isso pode ser visto no exemplo a seguir /media/ext4_evy/Ensino/UFSC/Ano2012/IIsemestre/public_html/…/aula110.html 2/7 11/10/12 Página de Evy Salcedo No código acima é impresso atribuído o numero 179 a uma variável de tipo caráter e logo é solicitado ao printf imprimir em tela sua representação em caráter (%c). Na linha 10 é colocado o valor hexadecimal (colocando 0x para avisar ao C que é Hexadecimal) que equivale ao digito binario 1 0 1 1 0 0 1 1. Para coverter o número de binario para Hexadecimal, dividimos o número binário em conjuntos de quatro digitos. Com quatro bits o máximo número que da para representar é o, 1111 → 15, como o sistema hexadecimal está constituído pelos dígitos {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F}, onde A → 10, B → 11 , C → 12 , D → 13 , E → 14 , F → 15 , resulta natural trabalhar nessa base. Uma vez dividido podemos converter para decimal cada conjunto é substituir pelo seu equivalente hexadecimal. No exemplo acima temos os grupos 1011 → 11 → B e 0011 → 3 → 3, assim 10110011 → 0xB3 Decimal Hexadecimal Binary 0 0 0000 1 1 0001 2 2 0010 3 3 0011 4 4 0100 5 5 0101 6 6 0110 7 7 0111 8 8 1000 9 9 1001 10 A 1010 11 B 1011 12 C 1100 13 D 1101 14 E 1110 15 F 1111 /media/ext4_evy/Ensino/UFSC/Ano2012/IIsemestre/public_html/…/aula110.html 3/7 11/10/12 Página de Evy Salcedo Agora apliquemos o operador &. No exemplo acima foram feitas as seguintes atribuições a ← 10110011 e a outra variável o número b ← 00000111 . Na linha 13 e realizada a operação entre às duas variáveis e atribuída à variável c, 10110011 & 00000111 , o resultado dessa operação é c ← 00000011 segundo a tabela. Convertendo para decimal obtemos: 7 6 5 4 3 2 1 0 0 ∗ 2 + 0 ∗ 2 + 0 ∗2 + 0 ∗ 2 + 0 ∗2 + 0 ∗2 + 1 ∗ 2 + 1 ∗2 = 3, que coincide com o valor impresso na tela. Neste exemplo é analisado 10110011 | 00000111 → 10110111 7 1 ∗ 2 6 + 0 ∗ 2 5 + 1 ∗2 4 + 1 ∗ 2 o . uso do operado Convertendo 3 + 0 ∗2 + 1 ∗2 2 1 + 1 ∗ 2 |. A para 0 + 1 ∗2 /media/ext4_evy/Ensino/UFSC/Ano2012/IIsemestre/public_html/…/aula110.html operação decimal analisada é obtemos: = 183 4/7 11/10/12 Página de Evy Salcedo Neste exemplo é analisado o uso do operado ^. A operação analisada é 00000111 → 10110100. Convertendo para decimal 7 1 ∗ 2 6 + 0 ∗ 2 5 + 1 ∗2 4 + 1 ∗ 2 3 + 0 ∗2 + 1 ∗2 2 1 + 0 ∗ 2 0 + 0 ∗2 ^ obtemos: 10110011 = 180 Neste exemplo é analisado o uso do operado ~. A operação analisada é ~10110011 → 01001100. Convertendo para decimal obtemos: 7 0 ∗ 2 6 + 1 ∗ 2 5 + 0 ∗2 4 + 0 ∗ 2 3 + 1 ∗2 + 1 ∗2 2 1 + 0 ∗ 2 0 + 0 ∗2 /media/ext4_evy/Ensino/UFSC/Ano2012/IIsemestre/public_html/…/aula110.html = 76 5/7 11/10/12 Página de Evy Salcedo Neste exemplo é analisado o uso do operado <<. A operação analisada é . Esse comando deslocou à esquerda todos os bits assim o bit zero passa para a posição 2, o 1 para posição 3, etc. O espaço deixado é preenchido com zeros. Convertendo para decimal obtemos: 7 6 5 4 3 2 1 0 1 ∗ 2 + 0 ∗ 2 + 0 ∗2 + 1 ∗ 2 + 1 ∗2 + 0 ∗2 + 0 ∗ 2 + 0 ∗2 = 152. Deve se ter claro que o deslocamento de bits não é uma rotação, os bits que saem à esquerda são apagados e o espaço que sobra à direita é preenchido com zero. 10110011 << 3 → 10011000 Neste exemplo é analisado o uso do operado >>. A operação analisada é . Esse comando deslocou à direita todos os bits assim o bit 7 passa para a posição 4, o 6 para posição 3, etc. O espaço deixado é preenchido com zeros. Convertendo para decimal obtemos: 7 6 5 4 3 2 1 0 0 ∗ 2 + 0 ∗ 2 + 0 ∗2 + 1 ∗ 2 + 0 ∗2 + 1 ∗2 + 1 ∗ 2 + 0 ∗2 = 22. 10110011 >> 3 → 00010110 /media/ext4_evy/Ensino/UFSC/Ano2012/IIsemestre/public_html/…/aula110.html 6/7 11/10/12 Página de Evy Salcedo Uma utilidade do deslocamento à direita é que pode servir como uma forma de multiplicar e dividir muito rápida. No exemplo acima definimos uma variável a como sendo uma variável de tipo unsigned long. Isso significa que não tem parte negativa (por isso unsigned) e tem tamanho de 32 bits ou 4 bytes (4*8 = 32), como mostra o resultado de sizeof(a) (linha 7) impresso na tela. Em a linha 9 assinamos o valor 100 à variável a; o qual é impresso na seguinte linha. Observe que se está utilizando como descritor de formato a opção %lu, no lugar de %d. A razão disso é que %lu diz para o printf que o número a ser impresso é do tipo unsigned (por isso o u), mas é de 4 bytes ou seja é um long, dai o l no descritor. Na linha 12 é realizado um deslocamento de uma posição à esquerda o que da como resultado que o nosso numero seja multiplicado por 2, como é impresso na tela (resultante do printf da linha 13). Na linha 15 atribuímos o valor constante de tipo sem sinal inteiro longo à variável a. Na linha 18 realizamos um deslocamento à esquerda do bits nessa variável e quando imprimimos vemos que o resultado é a metade do valor, ou seja 150. /media/ext4_evy/Ensino/UFSC/Ano2012/IIsemestre/public_html/…/aula110.html 7/7