A definição/declaração de ponteiros faz-se tal como para as outras variáveis, mas antecedendo o nome da variável de *:
int *p;A inicialização do valor do ponteiro p, fazendo com que aponte para a variável i definida anteriormente, faz-se à custa do operador endereço &:
int i;O acesso ao valor da variável apontada por p (ou seja, ao conteúdo do endereço), faz-se à custa do operador conteúdo (ou desreferenciação) *:
int *p;
p = &i;
cout << *p;O mesmo se passa para tipos definidos pelo utilizador. Por exemplo, a declaração de um ponteiro para uma variável da classe Aluno:
class Aluno {Não se deve confundir a definição/declaração de um ponteiro para uma variável com a utilização do operador conteúdo. Por exemplo:
...
};Aluno *p;
int i = 10;
int *p = &i; // definição de um ponteiro para int inicializado com o endereço de i.
cout << *p; // acesso ao conteúdo do endereço em p para a escrita do valor de i.
int m[20];então o endereço do elemento 4 (o quinto elemento) é igual ao endereço do elemento 3 somado de uma unidade. Ou seja, &m[4] = &m[3] + 1. Claro está que, ocupando os inteiros quatro bytes, estes endereços na realidade diferem de quatro unidades, mas isso é transparente para o utilizador: o compilador encarrega-se de calcular o tamanho das instâncias do tipo referenciado pelo endereço, neste caso int, de uma forma automática. De qualquer forma, o operador sizeof pode ser usado para saber quantos bytes ocupa cada instância dum dado tipo.
Numa expressão, o nome de uma matriz é sempre interpretado como um ponteiro constante para o respectivo primeiro elemento, excepto quando o nome ocorra como operando do operador sizeof. Sendo
int m[20];a ocorrência de m numa qualquer expressão é interpretada como significando o mesmo que &m[0]. Por outro lado, todas as operações de indexação do tipo m[i] são sempre interpretadas como significando *(m + i).
int m[20];ambas as instruções
int *p = m; // ou, o que é o mesmo, int *p = &m[0].
p[19] = 1;são válidas e têm o mesmo efeito.
m[19] = 1;
A soma de ponteiros com inteiros e a subtracção de inteiros de ponteiros, incluindo os operadores de incrementação e decrementação, estão bem definidos para ponteiros, desde que o endereço resultante se refira a um elemento (incluindo o fictício final) da mesma matriz (que pode ser dinâmica). Por exemplo, sendo
int m[20];ambas as instruções
int *p = m; // ou, o que é o mesmo, int *p = &m[0].
p += 3;
p[16] = 1;são válidas e têm o mesmo efeito.
m[19] = 1;
A subtracção de ponteiros também está bem definida desde que ambos se refiram a elementos válidos (incluindo o fictício final) da mesma matriz (que pode ser dinâmica). Dado o código atrás
cout << p - m << endl;tem como resultado aparecer
3no ecrã.
Isto significa que é sempre possível passar um ponteiro como argumento, na chamada a uma função, no lugar de um parâmetro especificado como uma matriz. Por exemplo, a função
int soma(int m[], int n);pode ser chamada da seguinte forma:
int matriz[] = {1, 2, 3, 4};A função soma() poderia ser implementada como se segue:
int *p = matriz; // ou seja, p = &matriz[0].
int z = soma(p, 4);
int soma(int m[], int n) {A utilização de ponteiros tem algumas semelhanças com a autilização de referências, nomeadamente porque permite a alteração do valor referenciado pelo ponteiro. Por exemplo, a funçao
int r = 0;
for(; n != 0; n--) {
r += *m;
m++;
}
}
void troca(int *x, int *y) {permite trocar os valores referenciados por dois ponteiros. O resultado de
int aux = *x;
*x = *y;
*y = aux;
}
int a = 10, b = 20;seria aparecer
troca(&a, &b);
cout << a << ' ' << b << endl;
20 10no ecrã. Repare-se que a chamada da função se faz usando o operador & explicitamente.
A função também pode ser usada com se segue:
int a = 10, b = 20;Finalmente, note-se bem a diferença face à utilização de referências propriamente ditas na versão alternativa abaixo:
int *pa, *pb;
pa = &a;
pb = &b;
troca(pa, pb);
cout << *pa << ' ' << *pb << endl;
void troca(int& x, int& y) {(Repare-se que, tal com o símbolo *, também o símbolo & tem um significado muito diferente numa expressão e numa declaração ou definição!)
int aux = x;
x = y;
y = aux;
}...
int a = 10, b = 20;
troca(a, b);
cout << a << ' ' << b << endl;
int main() {2. Escreva o seguinte programa e execute-o. Interprete o resultado e comente profusamente o programa.
int *p1;
int *p2;
int i = 2;
p1 = p2 = &i;
*p1 = 3;
cout << *p1 << " " << *p2 << " " << i << endl;
}
#include <iostream>3. Reescreva a função mostraMatriz() sem usar quaisquer variáveis locais (lembre-se que uma matriz, quando parâmetro de uma função, é na realidade um ponteiro).
using namespace std;void mostraMatriz(int m[], int n) {
for(int *p = m; p != m + n; p++) {
cout << *p;
if(p != m + n - 1)
cout << ' ';
}
cout << endl;
}int main() {
int a = 1;
int m[] = {1, 2, 3, 4, 5};
int b = 2;mostraMatriz(m,5);
cout << "Tamanho de um int: " << sizeof(int) << endl;
cout << "a: " << a << endl;
cout << "b: " << b << endl;cout << "&a: " << &a << endl;
cout << "&b: " << &b << endl;
cout << "&m[0]: " << m << endl;m[5] = 10;
m[6] = 20;cout << "a: " << a << endl;
cout << "b: " << b << endl;
}