Ponteiros no Pascal / Delphi – Ponteiro de Ponteiro

Este é um recurso de programação interessante, podemos ter ponteiros apontando para ponteiros. Abaixo um pequeno exemplo em Pascal / Delphi de como é a declaração e o uso de um ponteiro que aponta para um ponteiro:

program Project1;
{$APPTYPE CONSOLE}

uses SysUtils;

type
  PInteger = ^Integer;
  PPInteger = ^PInteger;
var
  p: PInteger;
  pp: PPInteger;
begin
  New(p);
  try
    pp := @p;
    p^ := 5;
    WriteLn(Format(
      ‘pp:%p, p:%p, pp^:%p, p^:%d, pp^^:%d’,
      [pp, p, pp^, p^, pp^^]));
  finally
    Dispose(p);
  end;
  ReadLn;
end.

Ao executarmos este programa, teremos o seguinte resultado:

pp:0040A600, p:00CF0870, pp^:00CF0870, p^:5, pp^^:5

pp foi definido como PPInteger, que pela declação type é um ponteiro de PInteger. p aponta para endereço de memória alocado por New, mas o próprio p é uma variável que contém um endereço, o endereço desta variável que contém o endereço pode ser obtido por @p. Por isso a declação pp := @p; não pega o endereço alocado por New e sim o endereço que o compilador reservou para a variável p. Prá lá de confuso! :-)

Para ajudar na explicação, vou aproveitar e citar um artigo do HowStuffWorks e fazer um paralelo.

Ponteiros para ponteiros

É possível e freqüentemente útil criar ponteiros de ponteiros. Esta técnica é às vezes chamada de handle e é útil em certas situações nas quais o sistema operacional precisa da capacidade de mover blocos de memória na pilha a seu critério. O exemplo a seguir demonstra um ponteiro de ponteiro:

 int **p;  
  int *q;  

  p = (int **)malloc(sizeof(int *));  
  *p = (int *)malloc(sizeof(int));
  **p = 12;
  q = *p;
  printf("%d\n", *q);  
  free(q);
  free(p);

Um paralelo com o Pascal / Delphi temos:

program Project1;
{$APPTYPE CONSOLE}

uses SysUtils;

type
  PInteger = ^Integer;
  PPInteger = ^PInteger;
var
  p: PPInteger;
  q: PInteger;
begin
  New(p);
  New(p^);
  try
    p^^ := 12;
    q := p^;
    WriteLn(q^);
  finally
    Dispose(q);
    Dispose(p);
  end;
  ReadLn;
end.

c-dds5b

O Windows e o Mac OS usam esta estrutura para permitir a consolidação de memória na pilha. O programa administra o ponteiro p, enquanto o sistema operacional administra o ponteiro *p. Uma vez que o sistema operacional gerencia *p, o bloco apontado por *p (**p) pode ser movido e *p pode ser alterado para refletir a transferência sem afetar o programa que utiliza p. Os ponteiros de ponteiros também são freqüentemente usados em C para identificar parâmetros de ponteiros em funções.

3 Respostas para “Ponteiros no Pascal / Delphi – Ponteiro de Ponteiro”


  1. 1 Analista

    É muito válida explicações sobre “PONTEIROS”, pois trazem muita confusão aos usuários e programadores.
    Parabéns pela iniciativa.

  2. 2 Alexandre

    Amigo, gostei do seu artigo, mas o PInteger, por natureza já é um ponteiro. Declarando como ^PInteger você estará fazendo um ponteiro de um ponteiro… Não entendi o objetivo de fazer esse tipo de declaração…

  3. 3 Alecão

    Alexandre, é muito difícil termos uma aplicação prática, mas como no artigo fala, pode ser útil quando precisamos realocar o ponteiro em lugar diferente. No windows é muito utilizado este recurso, é chamado de Handle. Verifique que nas APIs do Windows é comum a utilização de um Handle que é um inteiro que identifica um determinado recurso. Na prática funciona como um ponteiro para um ponteiro.

    Eu mesmo nunca utilizei este tipo de artifício em meus códigos Delphi. Mas quando fiz este artigo, achei interessante informar que este tipo de construção é possível na linguagem. Vai que alguém tem alguma ideia mirabolante? :-)

Deixe uma Resposta