Representao de Dados Representao binria Exemplo 1521310 111011012
Representação de Dados
Representação binária Exemplo: 1521310 = 111011012 Vantagens: • Implementação eletrônica – Possibilidade de armazenar elementos com dois estados – Transmissão eletrônica confiável (robustez a ruídos) – Implementação efienciente de operações artitméticas 0 3. 3 V 2. 8 V 0. 5 V 0. 0 V 1 0
Byte = 8 bits Faixa de valores em diferentes representações: – Binário: 00002 11112 – Decimal: 010 25510 – Hexadecimal 0016 FF 16 • Representação na base 16 • Dígitos são ‘ 0’ - ‘ 9’ e ‘A’ - ‘F’ • Escreva FA 1 D 37 B 16 em C como 0 x. FA 1 D 37 B ou 0 xfa 1 d 37 b al y im ar x c n He De Bi 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 A 10 1010 B 11 1011 C 12 1100 D 13 1101 E 14 1110 F 15 1111
Conversão entre bases • De base b para base 10 • De base 10 para base b – Divisões sucessivas por b; a cada iteração i o resto contém o numeral ai void num 2 string(int num, int base, char *b, int size) { int div, resto; int i = size - 2; div = num; while (div && i >= 0) { resto = div % base; if (resto < 10) b[i] = resto + '0'; else b[i] = (resto -10) + 'A'; div /= base; i--; } }. . . char buffer[11]; buffer[10]=0; num 2 string(num, base, buffer, 11);
A palavra (word) Cada máquina tem seu tamanho de palavra: =número de bits ocupados por um valor inteiro =número de bits de endereços • A maioria das atuais máquinas tem palavra de 32 bits (4 bytes) • Diferentes tipos de dados (p. ex. char, double) podem ocupar uma fração ou múltiplo do tamanho da palavra, mas sempre um número inteiro de bytes;
Tamanhos de Tipos em C …em bytes – Tipo C • • Alpha(64 bit) int long int char short float double long double ponteiro (tipo *) 4 8 1 2 4 8 8 8 32 -bit 4 4 1 2 4 8 8 4 Obs: sizeof(T) retona o número de bytes usado por tipo T IA 32 4 4 1 2 4 8 10/12 4
Memória orientada a palavras • Memória é um vetor de bytes (cada um com um endereço), mas acesso ocorre palavra a palavra • Endereço corresponde ao primeiro byte da palavra • Endereços de palavras subsequentes diferem de 4 em máquina de 32 bits 32 -bit 64 -bit Words Addr = 0000 ? ? Addr = 0004 ? ? Addr = 0008 ? ? Addr = 0012 ? ? Addr = 0000 ? ? Addr = 0008 ? ? Bytes Ender. 0000 0001 0002 0003 0004 0005 0006 0007 0008 0009 0010 0011 0012 0013 0014 0015
Ordenação de bytes Como organizar os bytes de uma palavra (4 bytes)? • Big Endian (computadores Sun, Mac) – byte menos significativo com maior endereço • Little Endian (computadores Alpha, PCs) – Byte menos significativo no menor endereço • Exemplo – variável y tem valor 0 x 01234567 (hexa) – Endereço &y é 0 x 100 Big Endian 0 x 100 0 x 101 0 x 102 0 x 103 01 Little Endian 23 45 67 0 x 100 0 x 101 0 x 102 0 x 103 67 45 23 01
Ordenação de Bytes • Transparente para o programador C • Relevante quando analisamos o código de máquina • Exemplo (litte endian): 01 05 64 94 04 08 add $Ox 8049464 %eax • Importante também para a transmissão de dados entre máquinas big e little endian
Verificar se a máquina é big ou little endian #include <stdio. h> typedef unsigned char *byte_ptr; void mostra (byte_ptr inicio, int tam) { int i; for (i=0; i<tam; i++) printf("%. 2 x", inicio[i]); printf("n"); } void mostra_int (int num) { mostra((byte_ptr) &num, sizeof(int)); }
Caracteres • Usa-se uma tabela para mapear inteiros (não negativos) em símbolos • Tabelas mais comuns: – ASCII – codificação em 8 bits ‘a’ ‘z’ ‘A’ 97 122 65 0 x 61 0 x 7 A 0 x 41 – UNICODE – codificação em 16 bits • Em C, tipo char define apenas 1 byte • Pode-se manipular um char como um int – Exemplo: if (c > ‘ 0’) val = c – ‘ 0’;
Operadores bit a bit em C • Podem ser aplicados a qualquer tipo C • Baseados na algebra booleana (1 = true, 0 = false) • And • Or – A & B = 1 quando A=1 e B=1 • Not – ~A = 1 quando A=0 – A | B = 1 quando A=1 ou B=1 • Or exclusivo (Xor) – A ^ B = 1 quando A=1 ou B=1, mas não ambos
Exemplos int a, b, c; a = 0 x. FF 00; b = 0 x 00 FF; c c = = a | b; a & b; ~a; a ^b; /* a = 1111 0000 */ /* b = 0000 1111 */ /* c = 0 x. FFFF */ /* c = 0 x 0000 */ /* c = 0 x 00 FF */ • Swap sem terceira variável: void troca (int *x, int *y) { *x = *x ^ *y; *y = *x ^ *y; *x = *x ^ *y; }
Deslocamento de bits (bit shifting): • x << n: shift p/ esquerda ( equivale a * 2 n) • x >> n: shift p/ direita ( equivale a / 2 n) – Shift lógico: bits mais significativos preenchidos com bit 0 – Shift aritmético: bits mais significativos preenchidos com o bit mais significativo original. • Exemplo: short int a, b, c; a = 0 x. F; b = 0 x 3 C; c = a << 4; c = b >> 2; /* /* a b c c = = 0000 0011 0 x. F 0 0000 1111 */ 1100 */ */ 1111 = 0 x. F */
Representação de tipos estruturados: arrays • Alocação contígua na memória • Primeiro elemento (a[0]) corresponde ao menor endereço de memória • Tipo a[tam] ocupa sizeof(Tipo)*tam bytes • O nome do array equivale a um ponteiro (cujo valor não pode ser alterado) • Exemplo: int a[tam], a é ponteiro constante tipo int *, e seu valor é &a[0] • Nomes de arrays passados como parâmetros são endereços (do array)
Aritmética básica com ponteiros Ponteiro é um endereço para um tipo específico de dado. P. ex. int *, char *, etc. Seja a declaração T *pa • Expressão *pa significa objeto T apontado por pa. E pa significa (endereço de objeto). • Expressão (pa +i) = pa + sizeof(T)*i • Exemplo: se int *pi, então (pi +3) é um deslocamento de 12 bytes do endereço pi. • O que significam? pa++, ++pa, (*p)++ • Comparação entre ponteiros (p == q, p >q ) só se são para o mesmo tipo • Subtração entre dois ponteiros, (p 1 – p 2), indica o número de elementos entre p 1 e p 2 • Existe equivalência entre arrays e ponteiros
Alocação para Arrays • Seja T A[L]; – Array de tipo T e comprimento L – Alocação contígua de L * sizeof(T) bytes • Exemplos: char string[12]; x x + 12 int val[5]; x x+4 x+8 x + 12 x + 16 x + 20 double a[4]; x x+8 x + 16 char *p[3]; x x+4 x+8 x + 24 x + 32
Arrays Aninhados #define PCOUNT 4 typedef int vetor[5]; vetor a[PCOUNT] = {{1, 5, 2, 0, 6}, {1, 5, 2, 1, 3 }, {1, 5, 2, 1, 7 }, {1, 5, 2, 2, 1 }}; vetor a[4]; 1 5 2 0 6 1 5 2 1 3 1 5 2 1 7 1 5 2 2 1 76 96 116 136 156 – Declaração “vetor a[4]” equivalente a “int a[4][5]” • Variável a denota array de 4 elementos – Alocados continuamente • Cada elemento é um vetor de 5 int’s – Alocados continuamente – Ordenação é por linha da matriz (elementos do vetor mais externo)
Alocação de Arrays Aninhados • Declaração T A[R][C]; – Tipo T – R linhas, C colunas – Elemento do tipo T ocupa K bytes • Tamanho do Array – R * C * K bytes • Ordenação principal por linha A[0][0] • • • A[0][C-1] • • • A[R-1][0] • • • A[R-1][C-1] int A[R][C]; A A [0] • • • [0] [1] • • • [1] [0] [C-1] 4*R*C Bytes • • • A A [R-1] • • • [R-1] [0] [C-1]
Estruturas Heterogêneas (structs) O alinhamento de structs na memória segue as regras: 1. Os campos são alocados na ordem em que aparecem na declaração; 2. Cada campo do struct que corresponde a uma palavra (ou múltiplas palavras) deve ser alocado em um endereço múltiplo de 4; shorts em múltiplos de 2 3. O início de cada estrutura tem que estar sempre alinhado em endereços múltiplos de 4 struct s{ Exemplo: sizeof(s 1) = 8; char c[2]; int i; } Ocupação dos bytes: c[0] x c[1] struct s s 1; i Padding = X+4 bytes não usados i i i
Padding no final • Para garantir o alinhamento do struct em um endereço múltiplo de 4, pode ocorrer um padding no final. • Exemplo: struct s{ int i; char c[2]; } sizeof(h) = 16; struct s h[2]; i h[0] i i i x h[1] c[1] X+4 i x+8 c[0] i i i c[0] X+12 c[1]
Exemplo de Alinhamento de structs struct s{ char c, d; int a; char e } struct s s 1; c d x a a a struct s{ short c, d; char e; short a } struct s s 2; a e X+4 sizeof(s 1) = 12 X+8 c c d d e x X+4 sizeof(s 2) = 8 a a X+8
- Slides: 22