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; }