Desde que uma
string é uma
array de elementos tipo
char, as operações com ponteiros ocorrem normalmente conforme visto em página anterior. Entretanto, alguns procedimentos específicos são úteis neste caso. Seja o programa a seguir.
#include <stdio.h>
main(){
int i;
char rua[] = "nova";
char *ptr = rua;
for (i=0; i<4; i++)
printf( "%d > %c\n", i, *ptr++ );
}
A saída desse programa seria
0 > n
1 > o
2 > v
3 > a
Strings têm um caractere nulo após o último elemento. Assim, uma versão mais elegante do programa seria obtida com o código seguinte.
#include <stdio.h>
main(){
int i = 0;
char rua[] = "nova";
char *ptr = rua;
while( *ptr )
printf( "%d > %c\n", i++, *ptr++ );
}
A saída seria a mesma do anterior. Entretanto o
loop while permite uma simplificação, isto é, o conteúdo apontado (
*ptr) pára o
loop quando chegar ao caractere nulo do final da
string.
Uma outra versão do programa é dada a seguir.
#include <stdio.h>
main(){
int i;
char rua[] = "nova";
char *ptr = rua;
for (i=0; i<4; i++)
printf( "%d > %c\n", i, *(rua+i) );
}
O código é quase idêntico ao primeiro, com a diferença do uso de
*(rua+i) no lugar de
*ptr++ no último argumento de
printf. Isso é possível porque, conforme já visto, o nome de uma
array é também um ponteiro para ela e pode ser usado como tal. E também poderia ser usado o clássico
rua[i].
Assim, as notações
*(rua+i)
rua[i]
são equivalentes e podem ser usadas sem distinção. Entretanto, muitos programadores preferem a notação de ponteiro,
*(rua+i), por ser de execução mais rápida sob certas condições. Mas não é só isso. Uma vez adquirido o hábito do uso de ponteiros, a notação específica dá uma aparência mais homogênea aos códigos.
Ponteiros como argumentos de funções |
Topo | Fim |
Quando uma função recebe uma variável como argumento, ela dispões de apenas uma cópia do valor dessa variável. Assim, se a variável é externa à função, o seu valor não pode ser modificado pela função. Mas se o
endereço (isto é, um ponteiro) da variável for passado à função, a modificação será possível. O uso de ponteiros também permite que uma função possa retornar mais de um valor. Seja o exemplo do programa a seguir.
#include <stdio.h>
void dobrar (int*, int*);
main(){
int a = 2, b = 4;
dobrar(&a, &b);
printf("a=%d b=%d", a, b);
}
void dobrar(int *ptr0, int *ptr1){
*ptr0 *= 2;
*ptr1 *= 2;
}
A saída deste programa seria:
a=4 b=8
Ou seja, as variáveis
a e
b, externas à função
dobrar, foram modificadas pela pela função e ela retornou mais de um valor.
Quando, no lugar de variáveis comuns, se usam ponteiros como argumentos de funções, o ganho de desempenho pode ser significativo se essas variáveis são objetos grandes como
arrays ou estruturas. Isso ocorre porque a função recebe uma cópia do argumento. Desde que um ponteiro contém apenas endereço, é eliminada a operação de copiar todo o objeto.
A noção de ponteiros permite supor que eles podem se referir a qualquer objeto localizado na memória. Tais objetos incluem também as funções e, portanto, é possível criar um ponteiro para uma função. A sintaxe é semelhante, mas há algumas regras próprias que podem ser observadas no programa de exemplo a seguir.
#include <stdio.h>
main(){
int (*ptrf) ();
ptrf = printf;
(*ptrf) ("Teste de ponteiro");
}
A saída do programa seria
Teste de ponteiro
Ou seja, a função
printf foi chamada através do ponteiro
ptrf.
Deve se observada a sintaxe indicada. Inclusive o tipo de dado na declaração do ponteiro
int (*ptrf) ();
deve ser o mesmo retornado pela função (
int) porque
printf retorna
int.
Ponteiros de funções permitem procedimentos avançados, como a criação de
tabelas de funções e a execução de cada uma de acordo com um determinado critério.