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);  

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.

Ponteiros para estruturas contendo ponteiros
Também é possível criar ponteiros para estruturas que contenham ponteiros. O exemplo seguinte usa o registro Addr da seção anterior:

  	typedef struct  
     {   		
        char nome[21];
  	char cidade[21];
  	char telefone[21];  
	char *comentário;
  	
    } Addr;  	
    Addr *s;  
    char comm[100]; 
    
    s = (Addr *)malloc(sizeof(Addr)); 
    gets(s->nome, 20);   	
    gets(s->cidade, 20);   
    gets(s->telefone, 20);   
    gets(comm, 100); 
    s->comentário =       
     (char *)malloc(sizeof(char[strlen(comm)+1]));
    strcpy(s->comentário, comm);   

O ponteiro s aponta para uma estrutura que contém um ponteiro que aponta para uma string de caracteres:


Neste exemplo, é muito fácil criar blocos perdidos se você não for cuidadoso. Por exemplo, aqui está uma versão diferente do exemplo AP.

  	s = (Addr *)malloc(sizeof(Addr));
  	gets(comm, 100);
  	s->comentário =
        (char *)malloc(sizeof(char[strlen(comm)+1]));
  	strcpy(s->comentário, comm);
   	free(s);  

Este código cria um bloco perdido, pois a estrutura que contém o ponteiro que aponta para a string é descartada antes que o bloco de string seja descartado, como mostrado abaixo:


Ligação
Finalmente, é possível criar estruturas capazes de apontar para estruturas idênticas. Esta capacidade pode ser usada para ligar uma string de registros idênticos em uma estrutura denominada lista encadeada.

   typedef struct
    {
   		char nome[21];
  		char cidade[21];
  		char estado[21]; 
 		Addr *next; 
    } Addr;  	
    Addr *first;  

O compilador permitirá que você faça isso e, com um pouco de experiência, ele pode ser usado para criar estruturas como esta demonstrada abaixo: