& para obter um apontador para um elemento de uma variável indexadaa é uma variável indexada, então &a[i] é um apontador para o i-ésimo elemento de a: int a[10], *p;
p = &a[0]; *p = 21;p aponta para um elemento de uma variável indexada, outros elementos podem ser obtidos usando aritmética de apontadores sobre p:p aponta o elemento a[i], então p+j aponta o elemento a[i+j]p = &a[2];
q = p + 3;p aponta o elemento a[i], então p-j aponta o elemento a[i-j]p = &a[2];
q = p - 2;int soma_vec(int vec[], int n) {
int *p, soma;
soma = 0;
for(p = &vec[0]; n>0; n--) {
soma += *p;
p++;
}
return soma;
} int a[10];
*a = 7; // coloca 7 em a[0]
*(a+1) = 12; // coloca 12 em a[1]
Em geral:
a+i |
é equivalente a | &a[i] |
a[i] |
é equivalente a | *(a+i) |
Podemos re-escrever a inicialização do ciclo
for(p = &vec[0]; n>0; n--) {
...
}como:
for(p = vec; n>0; n--) {
...
} int soma_vec(int vec[], int n) {
...
}
...
int a[N];
...
s = soma_vec(a, N); soma_vec(a, N) passa um apontador à função — não copia os elementos do vetorsoma_vec usando um apontador como argumento: int soma_vec(int *vec, int n) {
...
} int soma_vec(int vec[], int n) {
...
}soma_vec para somar apenas uma parte de um vetor: int a[100];
...
s = soma_vec(&a[30], 10);
// somar a[30], a[31], ... a[39] s = soma_vec(a+30, 10); int *max(int *pa, int *pb) {
if(*pa > *pb)
return pa;
else
return pb;
} max passamos dois apontadores: int *p, i, j;
...
p = max(&i, &j);max, p aponta para i ou para jchar *f( ... ) {
char tmp[MAX];
...
return &tmp[...]; // ERRO
}NULLDefinir uma função
char *find_alpha(char *str);NULL(Exercício 9.9: implementar uma função análoga.)
#include <stdlib.h>
#include <ctype.h>
char *find_alpha(char *str) {
while(*str != '\0' && !isalpha(*str)) {
str ++;
}
if (*str != '\0')
return str; // encontrou
else
return NULL; // não encontrou
}NULL é uma constante definida no header stdlib.h char texto[100], *ptr;
...
ptr = find_alpha(texto);
if(ptr != NULL)
printf("Primeira letra: %c\n", *ptr);
else
printf("Não existem letras!\n"); NULL para inicializar qualquer apontadorNULL leva a um erro de execução (e.g. "segmentation fault")int *p = NULL;
printf("%d", *p); // ERRO
*p = 42; // ERROVamos re-implementar algumas funções sobre cadeias usando apontadores:
unsigned comprimento(char *str) {
unsigned len = 0;
char *ptr = str;
while(*ptr != '\0') {
len ++;
ptr ++;
}
return len;
}Versão mais "idiomática": pós-incremento na condição do ciclo.
unsigned comprimento(char *str) {
unsigned len = 0;
char *ptr = str;
while(*ptr++ != '\0')
len++;
return len;
}Não é necessário a variável auxiliar ptr: podemos usar o argumento da função directamente.
unsigned comprimento(char *str) {
unsigned len = 0;
while(*str++ != '\0')
len++;
return len;
}void copiar(char *dest, char *origem) {
while(*origem != '\0') {
*dest = *origem;
dest ++;
origem ++;
}
*dest = '\0'; // colocar terminador
}Combinando a atribuição com o pós-incremento de apontadores.
void copiar(char *dest, char *origem) {
while(*origem != '\0')
*dest++ = *origem++;
*dest = '\0'; // colocar terminador
}void concat(char *dest, char *origem) {
// advançar até final do destino
dest += comprimento(dest);
// copia a origem
while(*origem != '\0')
*dest++ = *origem++;
*dest = '\0';
}Resultado 1 se as cadeias são iguais e 0 se são diferentes.
int comparar(char *str1, char *str2) {
while(*str1 != '\0' && *str1 == *str2) {
str1++;
str2++;
}
return (*str1 == *str2);
}