Professor Aquiles Burlamaqui UERN PONTEIROS Endereço Valor 00000000 ?? 00000001 ?? 00000002 ?? 00000003 ?? 00000004 ?? 00000005 ?? 00000006 ?? 00000007 ?? 00000008 ?? 00000009 ?? 0000000A ?? 0000000B ?? 0000000C ?? 0000000D ?? 0000000E ?? 0000000F ?? 00000010 ?? Célula A memória • Para um melhor entendimento do uso de ponteiros na linguagem de programação C é imprescindível compreender o seu relacionamento com a memória do computador em que o programa esta executando. • A memória é formada por várias células. Cada celular contém um endereço e um valor. • O Tamanho do endereço e o tamanho do valor depende da arquitetura do computador (ex: 32 bits ou 64 bits). Endereço 0000000D Valor ?? Célula Endereço Valor 00000000 ?? 00000001 ?? 00000002 ?? 00000003 ?? 00000004 ?? 00000005 ?? 00000006 ?? 00000007 ?? 00000008 ?? 00000009 ?? 0000000A ?? 0000000B ?? 0000000C ?? 0000000D ?? 0000000E ?? 0000000F ?? 00000010 ?? i Variáveis Caracteres int main() { char i; } • Declaro um caractere chamado i. Os caracteres ocupam 1 bytes na memória(para uma arquitetura de 32 bits). Endereço Variáveis Inteiras Valor 00000000 ?? 00000001 ?? 00000002 ?? 00000003 ?? 00000004 ?? 00000005 ?? 00000006 ?? 00000007 ?? 00000008 ?? 00000009 ?? 0000000A ?? 0000000B ?? 0000000C ?? 0000000D ?? 0000000E ?? 0000000F ?? 00000010 ?? i int main() { int i; } • Declaro um inteiro chamado i. Os inteiros ocupam 4 bytes na memória(para uma arquitetura de 32 bits) Endereço Variáveis Flutuantes Valor 00000000 ?? 00000001 ?? 00000002 ?? 00000003 ?? 00000004 ?? 00000005 ?? 00000006 ?? 00000007 ?? 00000008 ?? 00000009 ?? 0000000A ?? 0000000B ?? 0000000C ?? 0000000D ?? 0000000E ?? 0000000F ?? 00000010 ?? i int main() { float i; } • Declaro um número ponto flutuante chamado i. Os flutuantes ocupam 4 bytes na memória(para uma arquitetura de 32 bits) Endereço Valor 00000000 ?? 00000001 ?? 00000002 ?? 00000003 ?? 00000004 ?? 00000005 ?? 00000006 ?? 00000007 ?? 00000008 ?? 00000009 ?? 0000000A ?? 0000000B ?? 0000000C ?? 0000000D ?? 0000000E ?? 0000000F ?? 00000010 ?? Variáveis Flutuante Longo i int main() { double i; } • Declaro um número ponto flutuante grande chamado i. Os flutuantes ocupam 8 bytes na memória(para uma arquitetura de 32 bits) Endereço Valor 00000000 ?? 00000001 ?? 00000002 ?? 00000003 ?? 00000004 ?? 00000005 ?? 00000006 ?? 00000007 ?? 00000008 ?? 00000009 ?? 0000000A ?? 0000000B ?? 0000000C ?? 0000000D ?? 0000000E ?? 0000000F ?? 00000010 ?? Declaração de ponteiros c i f d int main() { char* c; int* i; float* f; double d; } • Declaração de quatro ponteiros(c,i,f e d). • Cada ponteiro de um tipo diferente(char, int, float, double). • Todos eles ocupam o mesmo espaço na memória, 4 bytes. • Isso acontece porque todos eles armazenam endereços de memória, e o tamanho de um endereço de memória é o mesmo para todos os tipos. Endereço Exemplo 1 Valor 00000000 ?? 00000001 ?? 00000002 ?? 00000003 ?? 00000004 ?? 00000005 ?? 00000006 ?? 00000007 ?? 00000008 ?? 00000009 ?? 0000000A ?? 0000000B ?? 0000000C ?? 0000000D ?? 0000000E ?? 0000000F ?? 00000010 ?? i int main() { int i; i = 15; char c = ‘s’; int * p = &i; *p = 25; } • Declaro um inteiro chamado i. Os inteiros ocupam 4 bytes na memória(para uma arquitetura de 32 bits) Endereço Exemplo 1 Valor 00000000 00 00000001 00 00000002 00 00000003 15 00000004 ?? 00000005 ?? 00000006 ?? 00000007 ?? 00000008 ?? 00000009 ?? 0000000A ?? 0000000B ?? 0000000C ?? 0000000D ?? 0000000E ?? 0000000F ?? 00000010 ?? i int main() { int i; i = 15; char c = ‘s’; int * p = &i; *p = 25; } • Faço uma atribuição. A variável i recebe o valor 15. Esse valor 15 é colocado no campo valor da memória alocada previamente para a variável i. • Lembrem que essa notação com o 15 na ultima casa é apenas didática na verdade esse valor é armazenado utilizando a notação complemento de 2(tudo em binário). Endereço Exemplo 1 Valor 00000000 00 00000001 00 00000002 00 00000003 15 00000004 s 00000005 ?? 00000006 ?? 00000007 ?? 00000008 ?? 00000009 ?? 0000000A ?? 0000000B ?? 0000000C ?? 0000000D ?? 0000000E ?? 0000000F ?? 00000010 ?? i c int main() { int i; i = 15; char c = ‘s’; int * p = &i; *p = 25; } • Variável c do tipo char criada e inicializada com o valor ‘s’. Uma variável do tipo char ocupa 1 byte na memória em nossa arquitetura 32 bits. Endereço Exemplo 1 Valor 00000000 00 00000001 00 00000002 00 00000003 15 00000004 s 00000005 00 00000006 00 00000007 00 00000008 00 00000009 ?? 0000000A ?? 0000000B ?? 0000000C ?? 0000000D ?? 0000000E ?? 0000000F ?? 00000010 ?? i c p int main() { int i; i = 15; char c = ‘s’; int * p = &i; *p = 25; } • Ponteiro de inteiro declarado. • O nome desse ponteiro é p e ele é inicializada no momento de sua criação. • O valor que esse ponteiro recebe ao ser inicializado é o endereço da variável i(&i) que nesse caso é o endereço 000000. • Dizemos que p aponta para i. Endereço Exemplo 1 Valor 00000000 00 00000001 00 00000002 00 00000003 25 00000004 s 00000005 00 00000006 00 00000007 00 00000008 00 00000009 ?? 0000000A ?? 0000000B ?? 0000000C ?? 0000000D ?? 0000000E ?? 0000000F ?? 00000010 ?? i c p int main() { int i; i = 15; char c = ‘s’; int * p = &i; *p = 25; } • Finalizando, fazemos uma atribuição. Colocamos 25 no valor apontado por p. Como visto no slide anterior p aponta para i. Desse modo, colocamos 25 no valor da variável i. Endereço Exemplo 2 Valor 00000000 ?? 00000001 ?? 00000002 ?? 00000003 ?? 00000004 ?? 00000005 ?? 00000006 ?? 00000007 ?? 00000008 ?? 00000009 ?? 0000000A ?? 0000000B ?? 0000000C ?? 0000000D ?? 0000000E ?? 0000000F ?? 00000010 ?? p1 int main() { char * p1; p1 = malloc(sizeof(char)); int * p2 = malloc(sizeof(int)*2); *p2 = 55; *(p2+1) = 11; } • Declaração de um ponteiro para char. Endereço Exemplo 2 Valor 00000000 00 00000001 00 00000002 00 00000003 04 00000004 ?? 00000005 ?? 00000006 ?? 00000007 ?? 00000008 ?? 00000009 ?? 0000000A ?? 0000000B ?? 0000000C ?? 0000000D ?? 0000000E ?? 0000000F ?? 00000010 ?? p1 int main() { char * p1; p1 = malloc(sizeof(char)); int * p2 = malloc(sizeof(int)*2); *p2 = 55; *(p2+1) = 11; } • O ponteiro p1 recebe o endereço da primeira posição do espaço reservado pela instrução malloc(...). Nesse caso o malloc aloca 1 byte: sizeof(char) é igual a 1. • Dizemos que p1 aponta para o byte reservado pelo malloc. Endereço Exemplo 2 Valor 00000000 00 00000001 00 00000002 00 00000003 04 00000004 ?? 00000005 00 00000006 00 00000007 00 00000008 09 00000009 ?? 0000000A ?? 0000000B ?? 0000000C ?? 0000000D ?? 0000000E ?? 0000000F ?? 00000010 ?? p1 p2 int main() { char * p1; p1 = malloc(sizeof(char)); int * p2 = malloc(sizeof(int)*2); *p2 = 55; *(p2+1) = 11; } • Declaração de um ponteiro para inteiro (p2). Esse ponteiro é inicializado com o valor da primeira posição do espaço alocado pelo malloc. • malloc(sizeof(int)*2) aloca 4*2 bytes,ou seja 8 bytes. O espaço equivalente a dois inteiros. Endereço Exemplo 2 Valor 00000000 00 00000001 00 00000002 00 00000003 04 00000004 ?? 00000005 00 00000006 00 00000007 00 00000008 09 00000009 00 0000000A 00 0000000B 00 0000000C 55 0000000D ?? 0000000E ?? 0000000F ?? 00000010 ?? p1 p2 int main() { char * p1; p1 = malloc(sizeof(char)); int * p2 = malloc(sizeof(int)*2); *p2 = 55; *(p2+1) = 11; } • O valor apontado por p2 recebe 55. Endereço Exemplo 2 Valor 00000000 00 00000001 00 00000002 00 00000003 04 00000004 ?? 00000005 00 00000006 00 00000007 00 00000008 09 00000009 00 0000000A 00 0000000B 00 0000000C 55 0000000D 00 0000000E 00 0000000F 00 00000010 11 p1 p2 *p2 *(p2+1) int main() { char * p1; p1 = malloc(sizeof(char)); int * p2 = malloc(sizeof(int)*2); *p2 = 55; *(p2+1) = 11; } • A valor apontado por p2+1 recebe 11. • Podemos somar ou subtrair do ponteiro. Com isso podemos fazer com o ponteiro aponte não somente para a primeira posição que lhe foi reservado. p2 => 00000009 + 1 (1 int => 4 bytes) p2+1 0000000D Endereço Exemplo 3 Valor 00000000 00 00000001 00 00000002 00 00000003 04 00000004 B 00000005 O 00000006 L 00000007 A • ---- 00000008 S Endereço 00000009 00 00000011 00 00000019 F 0000000A 00 00000012 00 0000001A 00 0000000B 00 00000013 00 0000001B 00 0000000C 0D 00000014 19 0000001C 04 0000000D F 00000015 B 0000001D B 0000000E ?? 00000016 O 0000001E O 0000000F ?? 00000017 L 0000001F L 00000010 ?? 00000018 A 00000020 A p1 int main() { char * p1 = malloc(sizeof(char)*5); char * p2 = malloc(sizeof(char)); *p2 = ‘F’; p1 = “BOLAS”; char * p3 = malloc(sizeof(char)*6); *p3 = *p2; *(p3+1) = *p1; *(p3+2) = *(p1+1); } p2 Valor Endereço p3 Valor