Esta é uma pré-visualização de arquivo. Entre para ver o arquivo original
*
*
*
Aula 21 – Ponteiros (1)
Declaração
Operadores & e *
Chamando funções por referência
Usando o qualificador const
*
*
* - 33
Objetivos
Ser capaz de usar ponteiros;
Ser capaz de usar ponteiros para passar argumentos de funções através de chamadas por referência;
Entender as relações entre ponteiros, arrays e strings;
Entender o uso de ponteiros para funções;
Ser capaz de declarar e usar arrays de strings.
*
*
* - 33
Introdução
Ponteiros possibilitam aos programas simular chamadas por referências e criar e manipular estruturas de dados dinâmicas;
Uma variável normalmente contém um valor específico;
Variáveis ponteiros contém, como seus valores, endereços de memória que contém valores específicos.
*
*
* - 33
Introdução
Variáveis ponteiros contém, como seus valores, endereços de memória que contém valores específicos.
Variável inteira
Variável ponteiro
*
*
* - 33
Introdução
O nome de uma variável referencia diretamente um valor;
Um ponteiro referencia indiretamente um valor.
*
*
* - 33
Declaração
Ponteiros devem ser declarados antes de serem utilizados;
int *notaPtr, nota;
double *raioPtr;
Ponteiros podem ser inicializados com 0, NULL ou um endereço;
*
*
* - 33
Operadores sobre ponteiros
O operador de endereço & retorna o endereço de seu operando;
int y = 5;
int *yPtr;
...
yPtr = &y;
endereço
de yPtr
endereço
de y
60024
O operador de endereço não pode ser aplicado:
a constantes;
a expressões que não resultam em referências; ou
a variáveis declaradas com classe de armazenamento register.
*
*
* - 33
Operadores sobre ponteiros
O operador de indireção ou de derreferência * , cria um sinônimo ou apelido para a variável:
int y = 5;
yPtr = y;
cout << *yPtr << endl;
Imprime o valor da variável y, isto é, 5.
*
*
* - 33
Operadores sobre ponteiros
Um ponteiro derreferenciado pode ser usado no lado esquerdo da atribuição:
*yPtr = 9;
Um ponteiro derreferenciado pode receber um valor fornecido:
cin >> *yPtr ;
9
*
*
* - 33
int main( )
{
int a;
int *aPtr;
a = 7;
aPtr = &a;
Declaração da variável inteira a
Declaração de um ponteiro para um inteiro aPtr
a recebe 7
aPtr aponta para a
*
*
* - 33
int a; int *aPtr; a = 7; aPtr = &a;
cout << "O endereco de a e' " << &a
<< "\nO valor de aPtr e' " << aPtr;
cout << "\n\nO valor de a e' " << a
<< "\nO valor de *aPtr e' " << *aPtr;
cout << "\n\nMostrando que * e & sao
inversos um do outro.\n&*aPtr = " <<
&*aPtr << "\n*&aPtr = " << *&aPtr <<
endl; return 0;
}
*
*
* - 33
O endereco de a e' 0x241ff5c
O valor de aPtr e' 0x241ff5c
O valor de a e' 7
O valor de *aPtr e' 7
Mostrando que * e & sao inversos um do outro.
&*aPtr = 0x241ff5c
*&aPtr = 0x241ff5c
int a; int *aPtr; a = 7; aPtr = &a;
cout << "O endereco de a e' " << &a
<< "\nO valor de aPtr e' " << aPtr;
cout << "\n\nO valor de a e' " << a
<< "\nO valor de *aPtr e' " << *aPtr;
*
*
* - 33
Chamando funções por referência
Existem 3 modos de passar argumentos em C++:
por valor;
por referência
com argumento de referência;
com argumento ponteiro.
*
*
* - 33
#include <iostream>
using namespace std;
int cuboPorValor( int );
int main( ) {
int num = 5;
cout << "O valor original de num e " << num;
num = cuboPorValor( num );
cout << "\nO atual valor de num e " << num << “\n\n”;
return 0;
}
int cuboPorValor( int n )
{
return n * n * n;
}
*
*
* - 33
#include <iostream>
using namespace std;
int cuboPorValor( int );
int main( ) {
int num = 5;
cout << "O valor original de num e " << num;
num = cuboPorValor( num );
cout << "\nO atual valor de num e “ << num << “\n\n”;
return 0;
}
int cuboPorValor( int n )
{
return n * n * n;
}
O valor original de num e 5
O atual valor de num e 125
*
*
* - 33
#include <iostream>
using namespace std;
void cuboPorReferencia( int * );
int main( ) {
int num = 5;
cout << "O valor original de num eh " << num;
cuboPorReferencia( &num);
cout<<“\n\nO novo valor de num eh ”<<num<<endl;
return 0;
}
void cuboPorReferencia( int *nPtr ) {
*nPtr = *nPtr * *nPtr * *nPtr;
}
recebe um ponteiro como argumento
derreferencia o ponteiro;
multiplica por ele mesmo 2 vezes; e
atribui à variável apontada
*
*
* - 33
#include <iostream>
using namespace std;
void cuboPorReferencia( int * );
int main( ) {
int num = 5;
cout << "O valor original de num eh " << num;
cuboPorReferencia( &num);
cout<<“\n\nO novo valor de num eh ”<<num<<endl;
return 0;
}
void cuboPorReferencia( int *nPtr ) {
*nPtr = *nPtr * *nPtr * *nPtr;
}
O valor original de num eh 5
O novo valor de num eh 125
*
*
* - 33
int main( )
{
int num = 5;
cuboPorReferencia( &num );
}
void cuboPorReferencia( int *nPtr )
{
*nPtr = *nPtr * *nPtr * *nPtr;
}
*
*
* - 33
int main( )
{
int num = 5;
cuboPorReferencia( &num );
}
void cuboPorReferencia( int *nPtr )
{
*nPtr = *nPtr * *nPtr * *nPtr;
}
*
*
* - 33
int main( )
{
int num = 5;
cuboPorReferencia( &num );
}
void cuboPorReferencia( int *nPtr )
{
*nPtr = *nPtr * *nPtr * *nPtr;
}
5
num
nPtr
125
*
*
* - 33
Usando const com ponteiros
Uma boa engenharia de software opta, sempre que possível, pelo princípio do menor privilégio
Se uma função não precisa alterar um valor que lhe é passado por argumento, utilize o qualificador const:
void printArray(const int[ ], const int tamanhoArray)
passar um array como const evita que ele seja modificado na função chamada.
*
*
* - 33
Passando ponteiros para uma função
ponteiro não constante para dado não constante ;
ponteiro não constante para dado constante ;
ponteiro constante para dado não constante ;
ponteiro constante para dado constante .
*
*
* - 33
1- ponteiro não constante p/ dado não constante
#include <iostream>
using namespace std;
#include <cstdlib>
#include <cctype>
void converteParaMaiuscula( char * );
int main( )
{
char string[ ] = "caracteres e R$32.98";
ponteiro para um char
string:
*
*
* - 33
cout << "O string antes da conversao eh: "
<< string;
converteParaMaiuscula( string );
cout << "\nO string depois da conversao
eh: “ << string << endl;
return 0;
}
O string antes da conversao eh: caracteres e R$32.98
string é passado como argumento
*
*
* - 33
ponteiro para string
void converteParaMaiuscula( char *sPtr )
{
while ( *sPtr != '\0' ) {
if ( islower( *sPtr ) )
*sPtr = toupper( *sPtr );
++sPtr; //move sPtr para o próximo caracter
}
}
C
A
R
A
C
T
E
R
E
S
E
ponteiro para um char
islower retorna:
verdadeiro, se o caractere que ela recebe é letra minúscula e
falso, caso contrario
toupper retorna:
o caractere da letra maíúscula correspondente à do argumento
*
*
* - 33
cout << "O string antes da conversao eh: "
<< string;
converteParaMaiuscula( string );
cout << "\nO string depois da conversao
eh: “ << string << endl;
return 0;
}
O string depois da conversao eh: CARACTERES E R$32.98
*
*
* - 33
2 - ponteiro não constante p/ dado constante
#include <iostream>
using namespace std;
#include <cctype>
void printCaracteres( const char * );
int main( )
{
char string[ ]=“imprime os caracteres de
um string”;
ponteiro para um char constante
O dado apontado é constante, o ponteiro, não.
*
*
* - 33
cout << "O string e': \n" <<
printCaracteres( string );
cout << endl;
return 0;
}
void printCaracteres( const char *sPtr ) {
// *sPtr não pode ser alterado, sPtr pode
for ( ; *sPtr != ‘\0’ ; sPtr++)
cout << *sPtr;
}
O string e’:
string
é passado como argumento
i
m
p
r
i
m
e
o
s
c
a
r
a
c
t
e
r
e
s
de um string
*
*
* - 33
2 - ponteiro não constante p/ dado constante
A passagem de estruturas (structs) para funções tem que ser feita por valor;
Para evitar o overhead, podemos passar um ponteiro para dados constantes.
*
*
* - 33
3 - ponteiro constante para dado não constante
É um ponteiro que sempre aponta para o mesmo endereço de memória;
Os dados dessa posição podem ser modificados através desse ponteiro;
Esse é o default para um nome de array
*
*
* - 33
int main( )
{
int x, y;
int * const ptr = &x;
cout << "ptr = " << ptr << endl;
*ptr = 7;
cout << "*ptr = " << *ptr << endl;
*ptr = 10;
cout << "*ptr = " << *ptr;
ptr = 0xf5c
*ptr = 7
*ptr = 10
ptr = &y;
return 0;
}
7
10
ptr é constante !!!
endereço
Valor
armazenado
*
*
* - 33
4 - ponteiro constante para dado constante
É um ponteiro que sempre aponta para o mesmo endereço de memória e;
Os dados dessa posição não podem ser modificados através desse ponteiro;
Ideal para quando se quer passar um array para uma função que apenas lê o array sem modificá-lo.
*
*
* - 33
int main( )
{
int x = 5, y;
const int * const ptr = &x;
cout << "ptr = " << ptr << endl;
cout << "*ptr = " << *ptr << endl;
*ptr = 10;
ptr = 0xf5c
*ptr = 5
ptr = &y;
return 0;
}