Ponteiros para estruturas

É possível criar um ponteiro para virtualmente qualquer tipo em C, incluindo tipos definidos pelo usuário. É extremamente comum criar ponteiros para estruturas. Um exemplo é mostrado abaixo:
  typedef struct
  {
  	char nome[21]; 
 	char cidade[21];  
 	char estado[3];
  } Rec;
  typedef Rec *RecPointer;
  
  RecPointer r;
  r = (RecPointer)malloc(sizeof(Rec));  

O pointeiro r é um ponteiro de estrutura. Observe que, como r é um ponteiro, ele retira 4 bytes de memória como qualquer outro ponteiro. Porém, a instrução malloc aloca 45 bytes de memória da pilha. *r é uma estrutura como qualquer estrutura de tipo Rec. A codificação seguinte mostra os usos freqüentes de variável de ponteiro:

  strcpy((*r).nome, "Leigh");
  strcpy((*r).cidade, "Raleigh"); 
  strcpy((*r).estado, "NC");
  printf("%s\n", (*r).cidade);
  free(r);  

Você lida com *r como lida com uma variável normal de estrutura, porém precisa ter cuidado com a precedência de operadores em C. Se deixasse de usar parênteses ao redor de *r, o código não compilaria, pois o operador "." tem maior precedência sobre o operador "*". Por se tornar tedioso digitar tantos parênteses ao trabalhar com ponteiros em estrutura, o C inclui uma anotação de taquigrafia que faz exatamente a mesma coisa:

  strcpy(r->nome, "Leigh");  

A notação r-> é equivalente ao (*r)., mas tem 2 caracteres a menos.

Ponteiros de matrizes
Também é possível criar ponteiros para matrizes:

  	int *p;
  	int i;  


  	p = (int *)malloc(sizeof(int[10]));  
  	for (i=0; i<10; i++) 
 		  p[i] = 0;
  	free(p);  

ou:

     int *p;  
     int i;  
  	p = (int *)malloc(sizeof(int[10]));  
  	for (i=0; i<10; i++)  
	   	     *(p+i) = 0;
  	free(p);  

Observe que ao criar um ponteiro para uma matriz de inteiros, você só precisa criar um ponteiro normal para int. A chamada para malloc aloca uma matriz de qualquer tamanho desejável e o ponteiro aponta para o primeiro elemento daquela matriz. Você pode indexar pela matriz apontada por p usando a indexação de matriz normal ou pode fazer isso usando a aritmética de ponteiros. A linguagem C vê ambas as formas como equivalentes.

Esta técnica particular é extremamente útil ao se trabalhar com strings. Ela permite alocar armazenamento suficiente para manter exatamente um string de determinado tamanho.

Matrizes de ponteiros
Às vezes, pode-se economizar bastante espaço ou resolver problemas de memória declarando uma matriz de ponteiros. No código de exemplo abaixo, uma matriz de 10 ponteiros de estruturas é declarada, em vez de declarar uma matriz de estruturas. Em vez disso, se uma matriz de estruturas tivesse sido criada, 243 * 10 = 2.430 bytes seriam necessários para a matriz. Usar a matriz de ponteiros permite que a matriz ocupe o menor espaço possível até que os registros reais sejam alocados com as instruções malloc. O código abaixo simplesmente aloca um registro, coloca um valor e descarta o registro para demonstrar o processo:

  	typedef struct
  	{  
		char s1[81];
  		char s2[81];  
	    	char s3[81];
  	} Rec;  
	   Rec *a[10];
    
  	a[0] = (Rec *)malloc(sizeof(Rec));
  	strcpy(a[0]->s1, "olá"); 
 	free(a[0]); 

Estruturas contendo ponteiros
As estruturas podem conter ponteiros, como mostrado abaixo:

     typedef struct  
     {  
		     char nome[21];
  		     char cidade[21];
  		     char telefone[21]; 
 		     char *comentario;  	
     } Addr;
     Addr s; 
     char comm[100];

     gets(s.nome, 20);  
     gets(s.cidade, 20);  
     gets(s.telefone, 20); 
     gets(com., 100);  	
     s.comentário =       
     (char *)malloc(sizeof(char[strlen(comm)+1]));  
     strcpy(s.comentario, com.);  


Esta técnica é útil quando apenas alguns registros realmente contêm um comentário no campo de comentário. Se não houver nenhum comentário para o registro, então o campo consiste em apenas um ponteiro (4 bytes). Depois, estes registros que têm um comentário alocam exatamente o espaço necessário para manter a string de caracteres do comentário, com base na extensão do string digitada pelo usuário.