&
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 j
char *f( ... ) {
char tmp[MAX];
...
return &tmp[...]; // ERRO
}
NULL
Definir 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; // ERRO
Vamos 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);
}