76091476-ponteiros
TRANSCRIPT
Programação CPonteiros
Fernando S. Pacheco
INSTITUTO FEDERAL DE EDUCAÇÃO, CIÊNCIA E TECNOLOGIA DE SANTA CATARINACAMPUS FLORIANÓPOLISDEPARTAMENTO ACADÊMICO DE ELETRÔNICA
ProgC Ponteiros 2
Sumário
● Ponteiros– Recapitulando variáveis– Aplicações– Operadores e inicialização– Argumento de funções– Aritmética de ponteiros– Relação com vetores (arrays)– Exemplos e cuidados– Ponteiros const
ProgC Ponteiros 3
Ponteiros
● Conceito importantíssimo em C● Recapitulando variáveis em C
– Variável é um espaço em memória com um nome específico e com valor que pode mudar
– Tamanho do espaço depende do tipo da variável
Endereço (byte)
kNome
Valor
0xA0 0xA1 0xA2 0xA3 0xA4 0xA5
Variável
Memória hipotética organizada em bytes
ProgC Ponteiros 4
Recapitulando variáveis
● Quando se declarachar k;
● 1 byte (8 bits) de memória é reservado (para guardar um valor inteiro)
● Uma tabela de símbolos mapeia o endereço reservado para o identificador k
ProgC Ponteiros 5
Recapitulando variáveis
● Quando, no programa, definesek=2;
● O valor 2 é colocado na porção de memória reservada para k
00000010
Endereço (byte)
kNome
Valor
0xA0 0xA1 0xA2 0xA3 0xA4 0xA5
Variável
ProgC Ponteiros 6
Recapitulando variáveis
● Observe que ao elemento k estão associadas duas informações– O próprio inteiro que está armazenado (2, p.ex.)– O “valor” da localização de memória, ou seja, o
endereço de k
● Há situações em que o que se deseja armazenar é um endereço
● Ponteiro é uma variável que armazena um endereço de memória, ou seja, aponta para um endereço
ProgC Ponteiros 7
Ponteiros
● Na figura, a caixa representa um espaço em memória
● var1 é o nome de um desses espaços● 2 é o valor que está armazenado nesse espaço● 0xA0 é o endereço desse espaço na memória
00000010
Endereço (byte)
Nome
Valor
0xA0
Variávelvar1
0xA0
0xA7
ptr_var1
ProgC Ponteiros 8
Ponteiros
● ptr_var1 é uma outra variável● ptr_var1 armazena o valor (endereço) 0xA0● Neste exemplo, é o endereço da variável var1
00000010
Endereço (byte)
Nome
Valor
0xA0
Variávelvar1
0xA0
0xA7
ptr_var1
ProgC Ponteiros 9
Ponteiros
● Dizse que ptr_var1 aponta para var1● Ponteiro também é chamado de variável de
endereço
00000010
Endereço (byte)
Nome
Valor
0xA0
Variávelvar1
0xA0
0xA7
ptr_var1
ProgC Ponteiros 10
Aplicações de Ponteiros
● Fazendo uma analogia com endereços físicos● O endereço é praticamente de mesmo tamanho● As casas em cada endereço podem ter
tamanhos diferentes
R. das
Letra
s, 45
R. das
Letra
s, 97
R. das
Letra
s, 10
3
R. das
Letra
s, 25
ProgC Ponteiros 11
Aplicações de ponteiros
● Observe o exemplo seguinte● Executando, verificase que tamanho dos
ponteiros é sempre o mesmo● Para plataforma 32 bits, é de 4 bytes
printf("tamanho de char: %d\n", sizeof(char));printf("tamanho do ptr para char: %d\n", sizeof(char*));printf("tamanho de int: %d\n", sizeof(int));printf("tamanho do ptr para int : %d\n", sizeof(int*));
ProgC Ponteiros 12
Aplicações de Ponteiros
● Voltando à analogia da casa/endereço● Uma aplicação é acessar estruturas de dados
(“casa”) através de ponteiros (“endereço”)● Mesmo para estruturas complexas, o acesso
será rápido
ProgC Ponteiros 13
Aplicações de Ponteiros
● Outra aplicação é retornar mais de um valor de uma função através de ponteiros
● Lembrar que no formato convencionaltipo_retorno nome_funcao(parametr1, parametr2)
float media(float nota1, float nota2)
● Só um valor pode ser retornado
ProgC Ponteiros 14
Declaração de ponteiros
● Colocar um asterisco na frente do nome da variávelint var1; // declara uma variável do tipo int
int *ptr_num; //declara um ponteiro do tipo int
● Cuidado com declaração de mais de um ponteiro na mesma linhaint p, q, r; // três variáveis comunsint *p, q, r; // cuidado! apenas p será um ponteiro!int *p, *q, *r; // agora temos três ponteiros
ProgC Ponteiros 15
Operadores para Ponteiros
Operador Significado
*
&
Dereference (dado um ponteiro, obtém o elemento referenciado)
Address_of (dado um elemento, aponta para o mesmo)
ProgC Ponteiros 16
Operadores para Ponteirosint var1; // declara variável do tipo int com o nome var1var1 = 4;
int *ptr_var1; //declara um ponteiro do tipo int
ptr_var1 = &var1; //ponteiro aponta para var1, ou seja, armazena o endereço de var1
*ptr_var1 = 5; //altera o valor que está armazenado no endereço apontado pelo ponteiro para 5
Código C Descrição
var1 Variável simples
&var1 Ponteiro para a variável var1 (endereço de var1)
Um inteiroptr_var1
Ponteiro para um inteiro (neste exemplo, aponta para a variável var1)
*ptr_var1
ProgC Ponteiros 17
Operações com Ponteiros
ProgC Ponteiros 18
Operações com Ponteiros#include <stdio.h>int main() { int i = 10; int *ptr; ptr = &i;
printf("Valor de i: %d\n", i); printf("Valor apontado por ptr: %d\n", *ptr); printf("Endereço de i: %p\n", &i); printf("Endereço apontado por ptr: %p\n", ptr); printf("Endereço de ptr: %p\n", &ptr); *ptr = 5; printf("Valor de i: %d\n", i); printf("Valor apontado por ptr: %d\n", *ptr); printf("Endereço apontado por ptr: %p\n", ptr); return(0);}
ProgC Ponteiros 19
Mais ponteiros
● Dois ou mais ponteiros podem apontar para o mesmo endereço
int val;
int *primeiro_ptr; /* um ponteiro */int *segundo_ptr; /* mais um ponteiro */
val = 1; /* atribui um valor para a variável * /
primeiro_ptr = &val; //O que está sendo feito aqui? Comentesegundo_ptr = primeiro_ptr; // E aqui? É válido fazer isso?
ProgC Ponteiros 20
Exercício 1
● Determine o que ocorre em cada linha do programa– Qual o valor final de c e d?int *a, *b, c = 3, d = 7;a = &c; b = &d; *a = 5;*b = 8; *a = *b; *a = 2; b = a; *b = 0;
ProgC Ponteiros 21
Resposta do Exercício 1
int *a, *b, c = 3, d = 7;a = &c; // a apontará para cb = &d; // b apontará para d*a = 5; // o valor em c é alterado (c=5)*b = 8; // o valor na variável d é alterado (d=8)*a = *b; // o valor de d (apontado por b) é // copiado para c (apontado por a) (c=8)*a = 2; // o valor na variável c é alterado (c=2)b = a; // b aponta para o mesmo lugar que a, // ou seja, para c*b = 0; // o valor de c é alterado (c=0)
ProgC Ponteiros 22
Exercício 2
● Determine o que ocorre em cada linha do programa– Qual o valor final de a e d?int a=5, *b, *c, d=8;b = &a;a = 7; c = &a;*c = 9;b = &d; *b = *c; *c = *b + *b; d = a; *b = 1;
ProgC Ponteiros 23
Inicialização de ponteiros
● Ponteiros devem ser inicializados antes de serem usados, ou seja, têm que apontar para um endereço específico antes do uso– Chamado wild pointer (ponteiro selvagem)– Fazer o seguinte levará a uma falha de
segmentação
int *p; /*ponteiro não inicializado*/*p = 9; /*o endereço físico para guardar o número 9 pode não ser válido*/
ProgC Ponteiros 24
Inicialização de ponteiros
● Compile e execute o programa seguinte● Observe o problema
ProgC Ponteiros 25
Inicialização de ponteiros#include <stdio.h>int main(){ int val = 7; int *ptr;
printf("Valor de val: %d\n", val); printf("Endereço apontado por ptr: %p\n", ptr);
printf("Valor apontado por ptr: %d\n", *ptr); /*observe que aqui haverá “lixo”, que poderia ser usado e traria consequências desastrosas*/ return(0);}
ProgC Ponteiros 26
Inicialização de ponteiros#include <stdio.h>int main(){ int val = 7; int *ptr=NULL; /*apontar para o endereço NULL (0), irá evitar que “lixo” seja usado, como no exemplo anterior*/
printf("Valor de val: %d\n", val); printf("Endereço apontado por ptr: %p\n", ptr);
printf("Valor apontado por ptr: %d\n", *ptr); /*irá gerar um SEG FAULT (falha de segmentação)*/ return(0);}
ProgC Ponteiros 27
Inicialização de ponteiros/*Mais um exemplo de problema*/#include <stdio.h>int main(){ int val = 7; int *ptr;
*ptr = 5; //aqui ocorrerá uma falha de segmentação (SEG FAULT) printf("Valor de val: %d\n", val); printf("Valor apontado por ptr: %d\n", *ptr); printf("Endereço apontado por ptr: %p\n", ptr); return(0);}
ProgC Ponteiros 28
Resumo até aqui
● Até aqui, vimos o que são ponteiros e como operálos
● Vamos ver, agora, uma aplicação importante– Funções com mais de um retorno através do uso
de ponteiros
ProgC Ponteiros 29
Ponteiros como argumentos de funções
● Em C, parâmetros são passados para uma função através de uma chamada por valor
● Valor do argumento é copiado para dentro da função
ProgC Ponteiros 30
Ponteiros como argumentos de funções
● Na chamada por valor o caminho só tem uma direção
ProgC Ponteiros 31
Ponteiros como argumentos de funções
● Mas usando ponteiros, é possível alterar o próprio parâmetro de entrada
● Assim, função poderá emular a existência de mais de um retorno
● Passagem por referência
● Vamos ver um exemplo prático
ProgC Ponteiros 32
Ponteiros como argumentos de funções
● Programa para trocar o valor de duas variáveis#include <stdio.h>int main(){ int a = 5; int b = 10; int temp; printf ("%d %d\n", a, b); temp = a; a = b; b = temp; printf ("%d %d\n", a, b); return 0;}
ProgC Ponteiros 33
Ponteiros como argumentos de funções
● E se essa operação tiver que ser repetida várias vezes? Como colocála em uma função?
● Verifique se o código seguinte faria isso.
ProgC Ponteiros 34
#include <stdio.h>void swap(int i, int j){ int temp; temp = i; i = j; j = temp;}int main(){ int a, b; a = 5; b = 10; printf ("%d %d\n", a, b); swap (a, b); printf ("%d %d\n", a, b); return 0;}
ProgC Ponteiros 35
Ponteiros como argumentos de funções
● Como fazer usando ponteiros#include <stdio.h>void swap (int *i, int *j) { int temp; temp = *i; *i = *j; *j = temp;}int main () { int a, b; a = 5; b = 10; printf ("\n\nValem a=%d, b=%d\n", a, b); swap (&a, &b); printf ("\n\nAgora, valem a=%d, b=%d\n", a, b); return 0;}
ProgC Ponteiros 36
Ponteiros como argumentos de funções
● Outro exemplo//contador é incrementado dentro da função#include <stdio.h>void inc_contador(int *conta_ptr){ (*conta_ptr)++;}
int main(){ int conta = 0; while (conta < 10) inc_contador(&conta); printf(“conta = %d\n”, conta); return (0);}
ProgC Ponteiros 37
Ponteiros como argumentos de funções
#include <stdio.h>
void inc_contador (int *conta_ptr){ (*conta_ptr)++;}
int main(){ int conta = 0; while (conta < 10) inc_contador(&conta); return (0);}
ProgC Ponteiros 38
Exercício
● Fazer uma função que receba o raio de um círculo e devolva o comprimento da circunferência e a área– Não use variáveis globais– Use ponteiros
● main() pergunta o raio para o usuário, chama a função e depois imprime o resultado
ProgC Ponteiros 39
Ponteiros como argumentos de funções
● Além de permitir que mais de um valor retorne, a passagem por referência tem outra vantagem– Não há cópia dos valores para dentro da função– Mais rápido e eficiente
● Principalmente para manipulação de vetores e estruturas
– Observe o exemplo seguinte● interessante monitorar a memória (no debugger)
ProgC Ponteiros 40
Ponteiros como argumentos de funções
#include <stdio.h>
void troca(char* string_ptr) { //frase não é copiada para dentro da função. É passado um ponteiro (endereço do início da string). *string_ptr='0'; //altera a primeira letra string_ptr++; *string_ptr='1'; //altera a segunda letra}
int main () { char frase[150]="Esta é uma string grande..."; printf ("\n\nfrase=%s\n", frase); troca(frase); printf ("\n\nAgora, frase=%s\n", frase); return 0;}
ProgC Ponteiros 41
Aritmética de Ponteiros
● A definição do tipo em ponteiros serve para– que o compilador saiba quantos bytes copiar para
uma posição de memória
int *ptr, var1; //plataforma com int 32
ptr = &var1;
*ptr = 2;● Neste exemplo, indica que 32 bits representando o
número 2 serão copiados para a área de memória apontada
– Além disso, também serve para fazer operações aritméticas com ponteiros
ProgC Ponteiros 42
Aritmética de Ponteiros
● Vamos imaginar que ptr do exemplo anterior aponta para o endereço (em bytes) 100 (decimal)
● Para qual endereço aponta (ptr+1)?
ProgC Ponteiros 43
Aritmética de Ponteiros
● Se ptr é do tipo int (4 bytes), o ponteiro irá apontar para o próximo endereço com um inteiro
● Neste caso hipotético, para o endereço 104
ProgC Ponteiros 44
Aritmética de Ponteiros
● Os operadores– ++, – comparação: >, <, >=, <=, ==, !=– São válidos com ponteiros e operam sobre os
endereços– Veja exemplo seguinte
ProgC Ponteiros 45
Aritmética de Ponteiros#include <stdio.h>int main(void) { int k=2010; int *ptr=&k;
printf("0. tamanho do int: %d\n", sizeof(int)); printf("0. endereço de k: %p\n", &k); printf("0. endereço apontado por ptr: %p\n", ptr);
ptr++; //para fins didáticos.Não deve ser acessado printf("1. endereço apontado por ptr: %p\n", ptr); ptr++; printf("2. endereço apontado por ptr: %p\n", ptr);
if (ptr>&k) { printf("endereço %p é maior que %p\n", ptr, &k); } return 0;}
ProgC Ponteiros 46
Ponteiros e Vetores (Arrays)
● Podemos continuar estudando a aritmética de ponteiros a partir de vetores
● Em C, os elementos de um vetor são guardados sequencialmente, a uma “distância” fixa um do outro
● Seja o seguinte (pont_vet1.c)
char array[5] = {5, 10, 15, 20, 25};char *array_ptr = &array[0];
ProgC Ponteiros 47
Ponteiros e Vetores (Arrays)
● Considerando a organização hipotética de memória da figura– Verifique o que é obtido comprintf(“%d %d”, *array_ptr, *(array_ptr+1));
– E com printf(“%d”,(*array_ptr)+1); ?
char array[5] = {5, 10, 15, 20, 25};char *array_ptr = &array[0];
ProgC Ponteiros 48
Ponteiros e Vetores (Arrays)
● Programa Exemplo– Definir vetor– Usar ponteiro para acessar cada valor– (No próximo exemplo, será vista a equivalência
com vetor)
ProgC Ponteiros 49
Ponteiros e Vetores (Arrays)
● Verifique a saída do programa (pont_vetor2.c)#include <stdio.h>int main (){ int i; int vetor[3] = {4, 7, 1}; int *ptr; ptr = vetor;// Em C é igual a ptr = &vetor[0] printf("Tam. do int nessa plataf.: %d\n\n", sizeof(int)); printf("End. vetor: %p\n", vetor); printf("End. apontado por ptr: %p\n", ptr); printf("End. onde está ptr: %p\n", &ptr); for (i = 0; i < 3; i++) { printf("O endereço do índice %d do vetor é %p\n", i, &ptr[i]); printf("O valor do índice %d do vetor é %d\n", i, ptr[i]); } return 0;}
ProgC Ponteiros 50
Ponteiros e Vetores (Arrays)
● C trata ponteiros e vetores da mesma forma● Assim, são equivalentes (programa anterior)
● Teste cada um deles e confira a equivalência!
vetor[i]; //”acesso” padrão vetorptr[i];
*(vetor + i); //”acesso” padrão ponteiro*(ptr + i);
printf("O valor do índice %d do vetor é %d\n", i, vetor[i]);...printf("O valor do índice %d do vetor é %d\n", i, *(ptr+i));
ProgC Ponteiros 51
Ponteiros e Vetores (Arrays)
– O programa seguinte verifica quantos elementos estão no vetor antes que apareça um 0
– Não usa ponteiros de forma explícita#include <stdio.h>
int array[] = {4, 5, 8, 9, 8, 1, 0, 1, 9, 3};int indice;
int main(){ indice = 0; while (array[indice] != 0) { ++indice; } printf("Numero de elementos antes de zero %d\n", indice); return (0);}
ProgC Ponteiros 52
Ponteiros e Vetores (Arrays)
● E este é o equivalente, usando ponteiros● Verifique como funciona#include <stdio.h>
int array[] = {4, 5, 8, 9, 8, 1, 0, 1, 9, 3};int *array_ptr;
int main(){ array_ptr = array;
while ((*array_ptr) != 0) { ++array_ptr; } printf("Numero de elementos antes do zero %d\n", array_ptr array); return (0);}
ProgC Ponteiros 53
Exemplo de Uso de Ponteiros
● Suponha que um nome esteja na forma “Silva/Maria”
● Desejase separálo em duas partes (sobrenome e nome)
ProgC Ponteiros 54
Exemplo de Uso de Ponteiros
● Como a barra é o separador, temos que procurála dentro da string de entrada
while (*string_ptr != caracter_procurar) {
● Dentro do laço, verificar se a string acabou e não encontramos a barra,
if (*string_ptr == '\0') return(NULL); ++string_ptr;}return(string_ptr); //aqui estará a posição do caracter procurado
ProgC Ponteiros 55
Exemplo de Uso de Ponteiros
● Depois de descobrir a posição da barra, falta separar as strings
ProgC Ponteiros 56
Exemplo de Uso de Ponteiros
● Função está no arquivo split_nome.c● A função strchr da biblioteca padrão string.h
faz isso, mas aqui foi usada uma versão própria para fins didáticos
ProgC Ponteiros 57
Cuidados no Uso de Ponteiros
● Em C, é fácil escrever código que seja difícil de entender
● Isso deve ser evitado● Nem sempre ter um código compacto é a
melhor solução● Legibilidade deve ser prioritária
ProgC Ponteiros 58
Cuidados no Uso de Ponteiros
● Não escreva programas assim (preced1.c)#include <stdio.h>int array[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};int main() { int *data_ptr; int valor; data_ptr = &array[0]; printf("0. data_ptr aponta = %p\n", data_ptr); valor = *data_ptr++; printf("1. valor = %d\n", valor); printf("1. data_ptr aponta = %p\n", data_ptr); valor = *++data_ptr; printf("2. valor = %d\n", valor); printf("2. data_ptr aponta = %p\n", data_ptr); valor = ++*data_ptr; printf("3. valor = %d\n", valor); printf("3. data_ptr aponta = %p\n", data_ptr); return(0);}
ProgC Ponteiros 59
Cuidados no Uso de Ponteiros
ProgC Ponteiros 60
Cuidados no Uso de Ponteiros
● O resultado depende da precedência dos operadores
● Para ficar mais claro, usar parênteses● Parênteses têm precedência maior● Mas verificar os programas
– preced1ponteiros.c– preced2ponteiros.c
ProgC Ponteiros 61
Cuidados com ponteiros
● Wild pointer: ponteiro não inicializado● aponta para endereço possivelmente inválido
– já vimos exemplos
● Dangling pointer: aponta para memória desalocada– Um dos bugs mais complicados de encontrar
● Porque, em um primeiro momento, o comportamento pode ser ok
– Mais em http://en.wikipedia.org/wiki/Dangling_pointer
ProgC Ponteiros 62
Cuidados com ponteiros#include <stdio.h>int* funcao(void) { int num = 1234; printf("O endereço de num: %p\n", &num); printf("O valor de num: %d\n", num); return #}
int main(void) { int *ptr; ptr=funcao(); printf("O endereço apontado por ptr: %p\n", ptr); printf("O valor apontado por ptr: %d\n", *ptr); // aqui já virou lixo, porque num está fora de escopo return(0);}
ProgC Ponteiros 63
Cuidados com ponteiros#include <stdio.h>int main(void) { int *ptr; { int num=21; //escopo de num é dentro deste bloco ptr=# printf("O endereço apontado por ptr: %p\n", ptr); printf("O valor apontado por ptr: %d\n", *ptr); } //num saiu de escopo printf("O endereço apontado por ptr: %p\n", ptr); printf("O valor apontado por ptr: %d\n", *ptr); // embora possa mostrar um num. ainda válido, é um problema em potencial return(0);}
ProgC Ponteiros 64
Cuidados com ponteiros#include <stdio.h>int main(void) { char frase[6]="12345"; char *ptr=frase; printf("caractere[0]=%c\n", *ptr); ptr++; printf("caractere[1]=%c\n", *ptr); ptr+=3; *ptr='A'; printf("caractere[4]=%c\n", *ptr); ptr++; printf("caractere[5]=%x\n", *ptr);//final da string (\0) ptr++;//saiu da "frase" *ptr='F';//está acessando endereço fora da string printf("caractere fora=%c\n", *ptr); printf("frase=%s\n", frase); return 0;}
ProgC Ponteiros 65
SAÍDA DO DEBUGGER (gdb)Breakpoint 1, main () at ponteiroforaescopo3.c:33 char frase[6]="12345";4 char *ptr=frase;6 printf("caractere[0]=%c\n", *ptr);(gdb) print &frase$1 = (char (*)[6]) 0xbf99964a(gdb) x/8cb 0xbf99964a0xbf99964a: 49 '1' 50 '2' 51 '3' 52 '4' 53 '5' 0 '\0' 74 'J' 106 '\226'7 ptr++;8 printf("caractere[1]=%c\n", *ptr);9 ptr+=3;10 *ptr='A';11 printf("caractere[4]=%c\n", *ptr);12 ptr++;
ProgC Ponteiros 66
SAÍDA DO DEBUGGER (gdb) (continuação)13 printf("caractere[5]=%x\n", *ptr);(gdb) x/8cb 0xbf99964a0xbf99964a: 49 '1' 50 '2' 51 '3' 52 '4' 65 'A' 0 '\0' 79 'O' 106 '\226'14 ptr++;//saiu da "frase"15 *ptr='F';//está acessando endereço inválido16 printf("caractere fora=%c\n", *ptr);17 printf("frase=%s\n", frase);(gdb) x/8cb 0xbf99964a0xbf99964a: 49 '1' 50 '2' 51 '3' 52 '4' 65 'A' 0 '\0' 70 'F' 106 '\226'18 return 0;19 }
ProgC Ponteiros 67
Cuidados com ponteiros
● Ver discussão emhttp://stackoverflow.com/questions/2583656/whatisthemeaningofwildpointerinc
ProgC Ponteiros 68
Ponteiros const
● O que está definido como constante em cada declaração?
const int result = 10;
const char *resposta_ptr = "Eletronica";
char *const nome_ptr = "IFSC";
const char *const teste_ptr = "Florianopolis";
ProgC Ponteiros 69
Ponteiros const
● O que está definido como constante em cada declaração?
const int result = 10; // result é um inteiro e o valor não pode ser alterado
const char *resposta_ptr = "Eletronica"; // os dados (char) são constantes, mas a variável resposta_ptr, não.//resposta_ptr é um ponteiro que pode apontar para outro endereço.//os dados apontados por resposta_ptr são constantes.
char *const nome_ptr = "IFSC"; // nome_ptr é um ponteiro que é constante.// os dados apontados por nome_ptr podem ser mudados.
const char *const teste_ptr = "Florianopolis"; //aqui, nem os dados nem o ponteiro podem ser alterados.
ProgC Ponteiros 70
Bibliografia e Crédito das Figuras
● OUALLINE, S. Practical C Programming. 3. ed. O'Reilly, 1997.
● ARGOUD, F. I. M. Introdução à Linguagem C (notas de aula). Florianópolis, 2009.
● http://home.netcom.com/~tjensen/ptr/pointers.htm
● http://br.geocities.com/cesarakg/pointers.html● http://pt.wikibooks.org/wiki/Programar_em_C/Ponteiros
● http://www.difranco.net/cop2220/opprec.htm