Representação de Dados Representação binária - PUC-Rio

Propaganda
Representação de Dados
Representação binária
Exemplo: 1521310 = 111011011011012
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
1
0
3.3V
2.8V
0.5V
0.0V
1
Byte = 8 bits
Faixa de valores em diferentes
representações:
– Binário: 000000002
111111112
– Decimal:
010
25510
– Hexadecimal
0016
FF16
• Representação na base 16
• Dígitos são ‘0’ - ‘9’ e ‘A’ - ‘F’
• Escreva FA1D37B16 em C como
0xFA1D37B ou 0xfa1d37b
al
im ary
c
x
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 num2string(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;
num2string(num, base, buffer,11);
2
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
•
•
•
•
•
•
•
•
•
int
long int
char
short
float
double
long double
tipo *
(*) 64 bits
Alpha(*)
32-bit
IA32
4
8
1
2
4
8
8
8
4
4
1
2
4
8
8
4
4
4
1
2
4
8
10/12
4
Obs: sizeof(T) retona o número de bytes usado por tipo T
3
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 Words
Addr
=
0000
??
Bytes Ender.
Addr
=
0000
??
Addr
=
0004
??
Addr
=
0008
??
Addr
=
0008
??
Addr
=
0012
??
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 x tem tem valor 0x01234567 (hexa)
– Endereço &x é 0x100
Big Endian
0x100 0x101 0x102 0x103
01
Little Endian
23
45
67
0x100 0x101 0x102 0x103
67
45
23
01
4
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 Ox8049464
• 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("%.2x", inicio[i]);
printf("\n");
}
void mostra_int (int num) {
mostra((byte_ptr) &num, sizeof(int));
}
5
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
0x61
0x7A
0x41
– 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)
• Or
• And
– A & B = 1 quando A=1 e B=1
• Not
& 0 1
0 0 0
1 0 1
– ~A = 1 quando A=0
~
0 1
1 0
– A | B = 1 quando A=1 ou B=1
| 0 1
0 0 1
1 1 1
• Or exclusivo (Xor)
– A ^ B = 1 quando A=1 ou B=1,
mas não ambos
^ 0 1
0 0 1
1 1 0
6
Exemplos
int a, b, c;
a = 0xFF00;
b = 0x00FF;
c
c
c
c
=
=
=
=
a | b;
a & b;
~a;
a ^b;
/* a = 1111 1111 0000 0000 */
/* b = 0000 0000 1111 1111 */
/* c = 0xFFFF */
/* c = 0x0000 */
/* c = 0x00FF */
• 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 * 2n)
• x >> n: shift p/ direita (Î equivale a / 2n)
– Shift lógico: bits mais significativos preenchidos com 0s
– Shift aritmético: bits mais significativos preenchidos
com 1s
• Exemplo:
short int a, b, c;
a = 0xF;
b = 0x3C;
c = a << 4;
c = b >> 2;
/*
/*
/*
/*
a
b
c
c
=
=
=
=
0000
0011
0xF0
0000
1111
*/
1100
*/
*/
1111 = 0xF */
7
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, (p1 – p2), indica o número
de elementos entre p1 e p2
• Existe equivalência entre arrays e ponteiros
8
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+8
x+4
x + 12
x + 16
x + 20
double a[4];
x
x+8
x + 16
x + 24
x + 32
char *p[3];
x
x+4
x+8
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)
9
Alocação de Arrays Aninhados
• Declaração
T A[R][C];
A[0][0]
– 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][C-1]
•
•
•
•
•
•
A[R-1][0] • • • A[R-1][C-1]
int A[R][C];
A
A
A
A
[0] • • • [0] [1] • • • [1]
[0]
[C-1] [0]
[C-1]
•
•
•
A
A
[R-1] • • • [R-1]
[0]
[C-1]
4*R*C Bytes
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
Exemplo:
struct s{
sizeof(s1) = 8;
char c[2];
int i;
}
Ocupação dos bytes:
c[0]
x
c[1]
struct s s1;
i
i
i
i
Padding =
X+4
bytes não usados
10
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
c[0]
c[1]
X+4
h[1]
i
i
i
x+8
i
c[0]
c[1]
X+12
Exemplo de Alinhamento de structs
struct s{
char c,d;
int a;
char e
}
struct s s1;
c d
x
a a a
struct s{
short c,d;
char e;
short a
}
struct s s2;
a e
X+4
sizeof(s1) = 12
X+8
c c d d e
x
X+4
a
a
X+8
sizeof(s2) = 8
11
Download