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.