Operadores e Expressões: bit-a-bit e especiais
Objetivos Em C, OPERADORES e EXPRESSÕES podem ser classificados em cinco grande categorias: Atribuições Aritméticos Lógicos e Relacionais Bit-a-Bit Especiais 2
Objetivos Na última aula, disticutimos as três primeiras categorias acima. Agora, iremos dar prosseguimento ao estudo apresentado os OPERADORES e EXPRESSÕES: Bit-a-Bit Especiais Ao final, concluiremos o assunto mostrando um quadro que resume e compara os OPERADORES da linguagem C por ordem de precedência e associatividade. 3
Manipulação de Bits OPERADORES e EXPRESSÕES de manipulação de bits ( bit-a-bit ) referem-se a testar, atribuir ou deslocar os bits efetivos em um byte ou palavra que correspondem aos tipos básicos char, int e variantes. OBS.: Operações bit-a-bit não podem ser feitas sobre float, double, long double, void ou outros tipos mais complexos. 4
5 Operadores bit-a-bit
Significados Os operadores &, e ~ têm a mesma tabela verdade que &&, e! (respectivamente), com a diferença que operam sobre os bits individuais da representação de dois números (ou apenas um, no caso de ~) e não sobre expressões numéricas. 6
Significados o operador ^ tem a mesma tabela verdade que a função xor() ou exclusivo o operador >> desloca os bits de um número k casas para à esquerda fazendo com que os k bits mais à esquerda se percam e os k bits mais à direita sejam '0 o operador << desloca os bits de um número k casas para à direita fazendo com que os k bits mais à direita se percam e os k bits mais à esquerda sejam '0' 7
Exemplo 1 (<< e >>): Considere: unsigned int x = 7; Se pudéssemos olhar a representação do valor 7 (decimal) 'dentro' da variável x, veríamos os seguinte padrão de bits: x = 0...00000111 ( a quantidade total de bits depende de quantos bytes são utilizados para armazenar um unsigned int, quantidade que depende da máquina alvo e compilador ). 8
Exemplo 1 (<< e >>): Considere: A EXPRESSÃO abaixo (deslocamento à esquerda): x = x << 2; faz com que o padrão de bits representando o valor inicial 7 se transforme em x = 0...00011100. Quer dizer, os bits, todos foram deslocados para a esquerda dois bits! Assim, o valor agora reresentado na variável x é 28! 9
Representação De maneira geral, se uma variável tem o seguinte padrão de bits: x = b n-1 b n-2... b 2 b 1 b 0 onde: a variável é representada por n bits cada um dos b i (para 0 i n-1 ) denota um bit com valor '0' ou '1' 10
Representação então: x << k, resulta em: x = b n-k-1 b n-k-2... b 2 b 1 b 0 0 0.. 0 0 0 onde a seq. final de '0's contém k '0's x >> k, resulta em: x = 0 0... 0 0 0 b n-1 b n-2... b k-1 b k onde a seq. inicial de '0's contém k '0's 11
Exemplo 2 (~): Continuando o exemplo anterior, tem-se x = 0...00011100. A EXPRESSÃO abaixo ( complemento de 1 ): x = ~ x; tem o seguinte efeito na representação de x em binário: x = 1...11100011. Ou seja, os bits que são '0' passam a ser '1', os que são '1' tornam-se '0'. 12
Exemplo 3 ( ) Continuando o exemplo anterior, tem-se x = 1...11100011. A EXPRESSÃO abaixo ( OR ): x = x 8 ; transforma x em : x = 1...11101011. Quer dizer, muda o quarto bit (da direita para a esquerda) de '0' para '1'. Isto acontece por que: 13
Exemplo 3 ( ) x = 1...11100011 4 = 0...00001000 ----------------- x 4 = 1...11101011 /* OU bit a bit */ é frequentemente utilizado para LIGAR bits particulares 14
Exemplo 4 (&) Continuando o exemplo anterior, tem-se x = 1...11101011. A EXPRESSÃO abaixo ( AND ): x = x & 0xf...f7 ; transforma x em : x = 1...11100011. Quer dizer, muda o quarto bit (da direita para a esquerda) de '1' para '0'. Isto acontece por que: 15
Exemplo 4 (&) x = 1...11101011 0xf...f7 = 1...11110111 ----------------- x 0xf...f7 = 1...11100011 /* AND bit a bit */ & é frequentemente utilizado para DESLIGAR bits particulares 16
Aplicações Rotinas de SO, drivers de dispositivos Criptografia Compactação de dados 17
Operadores Especiais Operador Condicional? : Operador sizeof Operadores de Conversão de Tipo ou Casting (tipo) Operador Vírgula, Operadores () e [] Serão vistos em mais detalhes em aulas futuras: Operadores de ponteiros * e & Operadores de estruturas. e -> 18
Operador Condicional? : Uso EXP1? EXP2 : EXP3; Significado EXP1 é avaliada... Se ela for verdadeira, então EXP2 é avaliada e se torna o valor da expressão como um todo.... Se EXP1 for falsa, então EXP3 é avaliada e se torna o valor da expressão como um todo. 19
Operador sizeof Uso sizeof ID-VAR; sizeof (ESP-TIPO); Significado sizeof é um operador unário em tempo de compilação que retorna o tamanho, em BYTES, de uma variável ou de um especificador de tipo de dados, este último escrito entre parênteses. 20
Conversão explicita de tipos (casting) Uso (ESPECIFICADOR-DE-TIPO) EXPRESSÃO; Significado Força - explicitamente - uma EXPRESSÃO a ser de um determinado tipo dado por ESPECIFICADOR-DE-TIPO. 21
Casting Além de conversões explícitas, o compilador realiza algumas conversões implícitas... 22
23 Casting
24 Casting
Operador virgula, Uso EXP1, EXP2; Significado O operador vígula é usado para encadear diversas expressões. O lado esquerdo (EXP1) é sempre avaliado como void. Assim, a expressão do lado direito (EXP2) torna-se o valor de toda a expressão separada por vírgula. 25
Operador virgula, int x,y; x = ( y = 3, y+1 ); primeiro o valor 3 é atribuído a y e, em seguida, o valor 4 é atribuído a x. Os parênteses são necessários porque o operador vírgula tem a menor precedência de todos os operadores de C. Um outro exemplo é: 26
Operador virgula, int i,x; for ( i = 0, x = 1; i < 10; i++, x+=2) {... } 27
Operadores [] e () Parênteses () são operadores que aumentam a precedência das operações dentro deles. Colchetes [] realizam indexação de vetores e matrizes. 28
Quadro geral de operadores em C A tabela a seguir lista a precedência de todos os operadores de C. Note que todos os operadores, exceto os operadores unários e o?, associam da esquerda para a direita. Os operadores unários ( *,! e ~) e o ternário? associam da direita para a esquerda. 29
Precedência de operadores em C 30
Ordem de Avaliação O padrão C ANSI (C89) não estipula que as subexpressões de uma expressão devam ser avaliadas e uma ordem específica. Assim, seu código nunca deve contar com a ordem em que as subexpressões são avaliadas. Por exemplo, a expressão: x = f() + g(); não garante que f() será chamada antes de g()! 31