A passagem por valor, padrão em C, não permite que uma função manipule diretamente uma variável que lhe esteja sendo passada. Quando se deseja manipular diretamente a variável, ponteiros devem ser usados como o recurso de acesso.
Para ilustrar esta condição, imagine como implementar a rotina swap que recebe dois argumentos de um mesmo tipo e troca seus valores. (Esta função poderia fazer parte de uma rotina de ordenação de elementos.) Por exemplo, para trocar dois inteiros, algo similar à seguinte função seria desejado:
/* * funcao (errada) de troca de inteiros */ void swap_err(int el1, int el2) { int temp; /* variavel temporaria */ temp = el1; el1 = el2; el2 = temp; }Entretanto, como observado no comentário inicial, esta função não funciona. Supondo que a função main de um programa tente acessar esta rotina, como em
main() { int a=10, b=20; void swap_err(int, int); printf("a=%d, b=%d\n", a, b); swap_err(a, b); printf("a=%d, b=%d\n", a, b); }A saída obtida seria:
a= 10, b= 20 a= 10, b= 20
Como se observa, a função swap_err não realiza a troca de valores das variáveis a e b de main, apesar de sua lógica interna estar correta. O que swap_err faz é trocar os valores das cópias destas variáveis, que são apenas suas variáveis locais.
A fim de se obter o efeito correto, ponteiros devem ser utilizados como argumentos. Assim, os elementos a serem trocados serão acessados por seus endereços, e seus conteúdos serão efetivamente alterados. Nesta nova versão, a função swap é definida como:
/* * funcao de troca de inteiros */ void swap(int *el1, int *el2) { int temp; /* variavel temporaria */ temp = *el1; *el1 = *el2; *el2 = temp; }A chamada à função deve passar os endereços das variáveis, como em
main() { int a=10, b=20; void swap(int *, int *); printf("a=%d, b=%d\n", a, b); swap(&a, &b); printf("a=%d, b=%d\n", a, b); }A saída obtida neste caso seria:
a= 10, b= 20 a= 20, b= 10como desejado.
Outros usos de ponteiros como argumentos incluem funções que devem retornar mais de um valor e a passagem de arranjos para funções. Quando um arranjo é passado para uma função, na verdade o que se passa é o endereço de seu primeiro elemento. Por este motivo, é possível omitir qual a dimensão do arranjo na declaração do tipo do argumento, como foi visto no caso de argv (Seção C.4). Quando o argumento é um arranjo multidimensional, apenas a dimensão do primeiro índice pode ser omitida -- as demais devem ser fornecidas. Caso contrário, seria impossível saber como acessar corretamente os elementos do arranjo.