www.samueldiasneto.com: Linguagem C - ponteiros

Pesquisar em todo o site
<<< Voltar Avançar >>>
Se esta página lhe ajudar, considere fazer uma doação

13. Ponteiros

13.1 Exibindo o endereço de memória de uma variável

Para exibir o endereço de memória de uma variável use o operador & antes da variável. Lembre-se que o valor da variável é uma coisa e o endereço de memória onde este valor está armazenado é outra. O código abaixo esclarecerá melhor estes conceitos:

/* exibindo o endereço de memória de variáveis */

#include <stdio.h>

int main()
  {
    char letra = 's';
    int idade = 35;
    char nome[10] = "samuel";
    float peso = 87.8;
    float altura = 1.82;

    printf("Exibindo o endereço de memória de variáveis\n\n");
    printf("O valor da variável letra é %c e seu endereço é %x\n",
	letra,&letra);
    printf("O valor da variável idade é %d e seu endereço é %x\n",
	idade,&idade);
    printf("O valor da variável nome é %s e seu endereço é %x\n",
	nome,nome);
    printf("O valor da variável peso é %2.1f e seu endereço é %x\n",
	peso,&peso);
    printf("O valor da variável altura é %1.2f e seu endereço é %x\n",
	altura,&altura);

  }
  

Ao ser executado, o código acima deverá exibir algo parecido com:

Exibindo o endereço de memória de variáveis

O valor da variável letra é s e seu endereço é bffff8cb
O valor da variável idade é 35 e seu endereço é bffff8c4
O valor da variável nome é samuel e seu endereço é bffff8b8
O valor da variável peso é 87.8 e seu endereço é bffff8b4
O valor da variável altura é 1.82 e seu endereço é bffff8b0

Observe na codificação que a variável nome não precisou do operador de endereço & pois matrizes já são tratadas como ponteiros pela linguagem C. Assim, quando o programa passa uma matriz para uma função, o compilador passa o endereço inicial da matriz.


13.2 Definição de ponteiros

Depois de entendida a diferença entre o valor de uma variável e seu endereço de memória fica fácil definir ponteiros.

Ponteiro é uma variável que armazena um endereço de memória.

OBSERVAÇÃO:Cabe aqui ressaltar que a linguagem C trata as matrizes como ponteiros, assim quando seu programa passa uma matriz para uma função, o compilador na verdade passa o endereço do primeiro elemento da matriz. Observe o exemplo abaixo:

/* verificando como C trata as matrizes como ponteiros */

#include <stdio.h>

int main()
  {
    int idade[5];
    float peso[5];
    char nome[10] = "samuel";

    printf("O endereço do primeiro elemento da matriz idade é %x\n",idade);
    printf("O endereço do primeiro elemento da matriz peso é %x\n",peso);
    printf("O endereço do primeiro elemento da matriz nome é %x\n",nome);

    return(0);
  }

13.3 Declarando uma variável ponteiro

A sintaxe para a declaração de uma variável ponteiro é:

TIPO *NOME

onde TIPO é um tipo de dados válido e NOME é o nome da variável. Exemplo:

int *idade;

13.4 Atribuindo valor a uma variável ponteiro

Como o ponteiro é uma variável que armazena um endereço de memória, você deverá atribuir a uma variável ponteiro um endereço de memória. Exemplo:

/* atribuindo valor a uma variável ponteiro */

#include <stdio.h>

int main()
  {
    int idade = 35;
    int *ptr_idade;

    ptr_idade = &idade; /* foi atribuído o endereço da variável
                           idade a variável ponteiro ptr_idade.
                           Observe o uso do operador & que devolve
                           o endereço de memória da variável
                           idade. */

    printf("O valor da variável idade é %d\n",idade);
    printf("O endereço da variável idade é %x\n",&idade);
    printf("O valor da variável ponteiro ptr_idade é %x\n",ptr_idade);

    return(0);
  }

13.5 Desreferenciando um ponteiro

Um ponteiro armazena um endereço de memória. Desreferenciar um ponteiro é acessar o valor armazenado neste endereço. Para isso você deve usar o operador de indireção, que é o asterisco * . Exemplo:

/* desreferenciando um ponteiro */

#include <stdio.h>

int main()
  {
    int idade = 35;
    int *ptr_idade;

    ptr_idade = &idade; /* foi atribuído o endereço da variável
                           idade a variável ponteiro ptr_idade.
                           Observe o uso do operador & que devolve
                           o endereço de memória da variável
                           idade. */

    printf("O valor da variável idade é %d\n",idade);
    printf("O endereço da variável idade é %x\n",&idade);
    printf("O valor da variável ponteiro ptr_idade é %x\n",ptr_idade);

    printf("O valor apontado por ptr_idade é %d\n",*ptr_idade);
    /* observe, na linha acima, o uso do operador de indireção ( * )
     * para desreferenciar o ponteiro ptr_idade e, assim, exibir
     * o valor armazenado no endereço de memória apontado por ele. */

    return(0);
  }

13.6 Alterando o valor armazenado no endereço apontado por um ponteiro

/* Alterando o valor armazenado no endereço apontado
 * por um ponteiro
 */

#include <stdio.h>

int main()
  {
    int numero = 35;
    int *ptr;

    ptr = № /* atribuindo o endereço de numero a ptr */

    printf("O ponteiro ptr armazena o endereço %x que,\npor sua vez,
	armazena o valor %d\n",ptr,*ptr);

    *ptr = 25; /* alterando o valor armazenado no endereço
                * apontado por ptr. Observe que o ponteiro
		* deve ser desreferenciado.*/

    printf("\nAgora o ponteiro ptr armazena o endereço %x que,
	\npor sua vez, armazena o valor %d\n",ptr,*ptr);

    return(0);
  }

13.7 Ponteiros como parâmetros de função

Quando queremos alterar o valor dos argumentos passados para uma função devemos definir os parâmetros da função como ponteiros. A isso denominamos chamada por referência. Exemplo:

/* ponteiros como parâmteros de função */

#include <stdio.h>

/* a função que recebe como argumento o valor
 * da variável não consegue alterar o valor
 * deste
 */
int valor(int a)
  {
    a = 35; /* alterando o valor do argumento passado */
  }

/* a função que recebe como argumento um ponteiro
 * consegue alterar o valor apontado por este
 */
int ponteiro(int *a)
  {
    *a  = 35; /* alterando o valor do argumento passado */
  }


int main()
  {
    int nr = 26;
    int *ptr_nr;

    printf("O valor inicial de nr é %d\n",nr);

    valor(nr); /* função que recebe o valor. Não consegue alterar este */
    printf("Valor de nr após a chamada da função valor = %d\n",nr);

    ptr_nr = &nr;
    ponteiro(ptr_nr); /* função que recebe ponteiro. Consegue alterar valor
                       * apontado
                       */
    printf("Valor de nr após a chamada da função ponteiro = %d\n",nr);

    return(0);
  }

13.8 Aritmética dos ponteiros

Você pode somar e subtrair valores a ponteiros, porém deve estar atento a um detalhe. Os ponteiros são endereços de memória, assim ao somar 1 a um ponteiro você estará indo para o próximo endereço de memória do tipo de dado especificado. Por exemplo, digamos que um ponteiro do tipo char aponta para o endereço 1000. Se você somar 2 a este ponteiro o resultado será um ponteiro apontando para o endereço 1002, pois o tipo char requer um byte de memória para armazenar seus dados. Se este ponteiro fosse do tipo int o resultado seria um ponteiro apontando para o endereço 1008, pois o tipo int, sob o linux, requer quatro bytes para armazenar seus dados. Então, sempre que for somar ou subtrair aos ponteiros você tem que trabalhar com o tamanho do tipo de dado utilizado. Para isso você pode usar o operador sizeof.

Analise o código abaixo para um melhor entendimento deste conceito:

/* visualizando como funciona a aritmética de ponteiros */

#include <stdio.h>

int main()
  {
    char letra[5] = {'a','e','i','o','u'};
    int contador, nr[5] = {30,12,67,13,41};

    char *ptr_letra;
    int *ptr_nr;

    ptr_letra = letra;
    ptr_nr = nr;

    printf("Visualizando como funciona a aritmética de ponteiros\n");

    printf("\nmatriz letra = a, e, i, o, u\n");
    printf("matriz nr = 30,12,67,13,41\n");

    printf("\nVerificando o tamanho dos tipos de dados\n");
    printf("tamanho do tipo de dado char   = %d\n",sizeof(char));
    printf("tamanho do tipo de dado int    = %d\n",sizeof(int));

    printf("\nPonteiro para letra aponta para %c no endereço %x\n",
	*ptr_letra,ptr_letra);
    printf("Ponteiro para nr aponta para %d no endereço %x\n",
	*ptr_nr,ptr_nr);

    printf("\nIncrementando os ponteiros\n");
    printf("ptr_letra + 3, ptr_nr + 2\n");

    ptr_letra += 3;
    ptr_nr += 2;

    printf("\nPonteiro para letra agora aponta para %c no endereço %x\n",
	*ptr_letra,ptr_letra);
    printf("Ponteiro para nr agora aponta para %d no endereço %x\n",
	*ptr_nr,ptr_nr);

    return(0);
  }

13.9 Exibindo uma string usando um ponteiro

Uma string é uma matriz de caracteres. Podemos usar um ponteiro para exibí-la assim:

/* exibindo uma string usando um ponteiro */

#include <stdio.h>

int main()
  {
    char string[40] = "Exibindo uma string usando um ponteiro.";
    char *ptr_str;

    /* Apontando para a string */
    ptr_str = string;
    printf("Apontando para o inicio da string => ptr_str = %c\n\n",
	*ptr_str);

    /* Exibindo toda a string usando o ponteiro */
    while(*ptr_str)
      {
        putchar(*ptr_str);
        ptr_str++;
      }
    printf("\n");

    return(0);
  }

13.10 Criando uma função que retorna um ponteiro

#include <stdio.h>
#include <ctype.h>

/* Função que converte uma strig para maiúsculas.
 * Esta função retorna um ponteiro
 */
char *converte_maiuscula(char *string)
  {
    char *inicio_da_str, *auxiliar;
    inicio_da_str = auxiliar = string;
    while(*string)
      {
        *auxiliar = toupper(*string);
        string++;
        auxiliar++;
      }
    return(inicio_da_str);
  }


int main()
  {
    char string[80] = "Usando uma função que retorna uma string.";

    printf("%s\n",string);

    converte_maiuscula(string);

    printf("%s\n",string);

    return(0);
  }

13.11 Matriz de ponteiros/strings

A linguagem C lhe permite criar matrizes de ponteiros. O uso mais comum para este tipo de matriz é conter strings. Abaixo segue um exemplo da declaração de uma matriz que armazena ponteiros para strings:

char *dias(7) = {"Domingo","Segunda","Terça","Quarta",
"Quinta","Sexta","Sábado"};

OBSERVAÇÃO:Em matrizes de ponteiros para strings a linguagem C não inclui um item NULL para indicar o final da matriz, você tem que fazer isso.


13.12 Percorrendo uma matriz de strings com um laço for

/* percorrendo uma matriz de strings com um laço for */

#include <stdio.h>

int main()
  {
    char *dias[7] = {"Domingo","Segunda","Terça","Quarta",
	"Quinta","Sexta","Sábado"};
    int contador;

    for(contador = 0;contador < 7;contador++)
      printf("%do dia da semana = %s\n",contador+1,dias[contador]);

    return(0);
  }

13.13 Percorrendo uma matriz de strings com um ponteiro

/* percorrendo uma matriz de strings com um ponteiro */

#include <stdio.h>

int main()
  {
    char *dia[] = {"Domingo","Segunda","Terça","Quarta",
	"Quinta","Sexta","Sábado",0};
    char **ptr_dia;

    /* *dia é um ponteiro para uma string e
     * **ptr_dia é um ponteiro para um ponteiro para uma string
     */

    ptr_dia = dia; /* apontando ptr_dia para o início da matriz dia */

    while(*ptr_dia)
      {
        printf("%s\n",*ptr_dia);
        ptr_dia++;
      }

    return(0);

  }

  /* Quando você declara uma matriz de strings o compilador
   * não acrescenta um caractere NULL para indicar o final
   * da matriz como o faz com uma matriz de caracteres (strings).
   * Por isso você mesmo tem que inserir o caractere NULL para
   * indicar o final da matriz.
   *
   * Foi isso que foi feito ao inserir 0 no final da matriz dia
   */

13.14 Ponteiro para função

Você pode criar um ponteiro para uma função. O uso mais comum deste recurso é para passar uma função como parâmetro para outra função. A declaração de um ponteiro para uma função segue a sintaxe:

TIPO (*FUNÇÃO)();

Observe o uso disto no exemplo abaixo:

/* exemplificando o uso de ponteiro para uma função */

#include <stdio.h>

/* função que identifica o maior entre dois inteiros */
int maior(int nr1,int nr2)
  {
    return((nr1 > nr2) ? nr1 : nr2);
  }

/* função usa_maior(). Recebe dois inteiros e um
 * ponteiro para a função maior()
 */
int usa_maior(int x,int y, int (*maior)())
  {
    return(maior(x,y));
  }

int main()
  {
    int a,b;

    printf("Entre com o primeiro número: ");
    scanf("%d",&a);
    printf("Entre com o segundo número: ");
    scanf("%d",&b);
    printf("O maior entre os dois é %d\n",usa_maior(a,b,&maior));
    /* observe logo acima que usa_maior() recebe como argumentos
     * dois números inteiros e o endereço da função maior()
     * sendo, assim, coerente com sua declaração
     */

    return(0);
  }

Se esta página lhe ajudou, considere fazer uma doação
<<< Voltar Avançar >>>