PONTEIROS


  Foi visto até aqui, que as variáveis armazenam dados na memória e esses dados podem ser de diversos tipos. Elas localizam-se em uma área separada do código executável, onde cada variável é um bloco de memória contendo informações como o tipo de dado, nome (ou identificador) e o dado em si.
  As varáveis que foram apresentadas até o presente momento são do tipo estáticas. Entretanto, elas podem ser de dois tipos: estáticas ou dinâmicas.
  Uma variável do tipo estática é uma variável que contém o valor do dado e este está sempre no mesmo lugar da memória. Por outro lado, uma variável do tipo dinâmica contém o endereço para o dado, em vez do dado em si. Dessa forma, a localização do dado pode variar livremente.
  Um exemplo para ilustrar a diferença entre variáveis estáticas e dinâmicas é o seguinte: uma variável estática é a A_CASA que contém o dado, enquanto que uma variável dinâmica é o ENDEREÇO_PARA_A_CASA que contém o dado.
  Um ponteiro declara uma variável do tipo dinâmica e sua representação em C é o sinal de asterisco "*".

  Obs: recomenda-se o estudo do capítulo de ponteiros do curso de Pascal, pois ele está completo e revisado. Dessa forma, o capítulo de ponteiros do C irá apenas abordar as sintaxes de ponteiros do C, diferenciando-as do Pascal.

  Sintaxe:
 <tipo_de_dado> *<identificador>;

  Exemplo:
 int *p;

  Alocação de Memória

  A alocação de memória em C++ é igual ao Pascal, através do comando new(). Entretanto, a linguagem C mais antiga aloca memória através dos comandos malloc, calloc e realloc. Sintaxes:
 ponteiro = malloc(tamanho_do_vetor * tamanho_da_variavel);
 ponteiro = calloc(tamanho_do_vetor, tamanho_da_variavel);
 ponteiro = realloc(ponteiro_antigo, tamanho_do_vetor * tamanho_da_variavel);

  Exemplo de uso do malloc:
 p = (int *) malloc(1 * 4);
  Aloca 4 bytes para uma variável inteira, devolvendo a referência de memória para o ponteiro p.

  Podemos utilizar a função sizeof() para calcular o tamanho de um tipo variável automaticamente. Ex:
 p = (int *) malloc(sizeof(int));

  A diferença entre malloc e calloc é que calloc atribui a todos os elementos do vetor o valor igual a zero, enquanto que o malloc deixa o "lixo" da memória.
  Já a função realloc aloca uma nova área de memória, reajustando o tamanho do vetor antigo. Ele copia os dados.
  O comando que libera espaço em memória para um recurso alocado por malloc ou calloc é o free. Ex:
  free(p);

  Dicas:
  1. A alocação dinâmica não memoriza o tamanho do bloco de dados reservados. Assim, o programador deverá memorizar o tamanho do vetor em uma variável.
  2. Uma string é um vetor de caracteres, onde o último byte é sinalizado com o valor igual a 0.

  Lidando com ponteiros

  Foi visto que um ponteiro contém uma referência à localização do dado, enquanto que uma variável estática contém o dado diretamente. Assim, quando uma variável do tipo ponteiro é utilizada sem o asterisco "*", significa que estamos referenciando a um local de memória. Quando o asterisco é utilizado, estamos acessando o dado referenciado pelo ponteiro. Veja o exemplo a seguir:
#include <stdio.h>
#include <stdlib.h>

unsigned char *p;

void main(void)
{
  p = (char *) malloc(sizeof(char));

  *p = 4;

  printf("Valor de p: %d\n", *p);
}
  Saída:
  Valor de p: 4

  Assim como no Pascal, podemos referenciar variáveis estáticas com um ponteiro. No caso do C, utilizamos o símbolo "&" para obter o endereço de uma variável estática. Ex:
  int i, *p;

  p = &i;

  Testando em um programa:
#include <stdio.h>
#include <stdlib.h>

int i, *p;

void imprime()
{
  printf("Valor de i: %d\n", i);
  printf("Valor de p: %d\n", *p);
}

void main(void)
{
  i = 10;
  p = &i;

  imprime();

  *p = 5;

  imprime();
}
  Saída:
  Valor de i: 10
  Valor de p: 10
  Valor de i: 5
  Valor de p: 5

  Ponteiros para tipos diferentes:
#include <stdio.h>
#include <stdlib.h>

int i;
unsigned char *p;

void main(void)
{
  i = 4;
  p = (char *)&i; // Casting - conversão entre tipos diferentes

  int f;

  for (f=0; f < sizeof(int); f++)
    printf("%02d - %02X\n", f, *(p+f));
}
  Saída:
  00 - 04
  01 - 00
  02 - 00
  03 - 00

  Podemos substituir o trecho do laço "for" por:
for (f=0; f < sizeof(int); f++)
{
    printf("%02d - %02X\n", f, *p);
    p++;
}
  Ou:
for (f=0; f < sizeof(int); f++)
    printf("%02d - %02X\n", f, *p++);

  Ponteiros em Estruturas (Struct)

  Foi visto que a referência a um elemento de uma variável estática do tipo "struct", é feita através de um ponto ".". No caso dos ponteiros, utiliza-se os símbolos "->". Ex:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct ficha
{
  char nome[20];
  int idade;
  struct ficha *proximo;
} *p;

void main(void)
{
  p = (struct ficha *) malloc(sizeof(struct ficha));

  strcpy(p->nome, "Gloria");
  p->idade = 20;

  printf("Nome: %s.\n", p->nome);
  printf("Idade: %d anos.\n", p->idade);
}
  Saída:
  Nome: Gloria.
  Idade: 20 anos.

  Observe que a referência aos dados da estrutura não possuem asterisco, uma vez que essas variáveis são do tipo estática.


/MARMSX/CURSOS/C--