Ponteiros em C

De Wiki Cursos IFPR Foz
Ir para navegaçãoIr para pesquisar

Ponteiros em C

Um ponteiro é uma variável que contem o endereço de uma variável.

O operador & fornece o endereço de uma variável. Por exemplo, de c é um char e p é um ponteiro,

 p=&c

atribui a p o endereço da variável c. Diz-se, portanto, que "p aponta para c".

O operador * quando aplicado a um ponteiro acessa o objeto apontado por ele. Por exemplo, suponha que x e y são inteiros e ip é um ponteiro para int. A sequência abaixo mostra como usar & and *[1]:

 int x=1, y=2;
 int *ip;     /* ip é um ponteiro para int */
 ip = &x;     /* ip agora aponta para x */
 y = *ip;     /* y agora é 1 */
 *ip = 0;     /* x agora é 0 */

Na declaração de variáveis ponteiro, cada ponteiro aponta para o tipo de dado declarado, se comportando como tal.

Por exemplo, se ip aponta para o inteiro x, então *ip pode ocorrer no contexto que x ocorre, portanto,

 *ip = *ip + 10; /*Incrementa *ip de 10 (ou incrementa x de 10)*/
 y = *ip + 1     /*pega o que ip aponta e soma 1 e atribui a y*/
 *ip += 1        /*Incrementa *ip de 1*/

Ponteiros e argumentos de funções

A linguagem C passa argumentos para funções por valor. Portanto, não há como acessar diretamente as variáveis usadas para chamar a função. Para acessar em uma função as variáveis fornecidas como argumentos deve-se utilizar ponteiros, que apontam para as variáveis.

Exemplo 1
Função que modifica uma variável do programa principal[2]:
 #include <stdio.h>
 void Func(int *y);                      /*Protótipo da função*/
 void main ()                            /*Programa principal para teste*/
 {
   int x=15;
   printf("Primeiro valor de x=%d\n", x);
   Func(&x);
   printf("Segundo valor de x=%d\n", x);
 }
 void Func(int *y)                       /*Definição da função*/
 {
   ++*y;
   printf("Valor de y=%d\n", *y);
 } /* fim Func */
Exemplo 2
Função Swap que faz intercâmbio do valor de duas variáveis[1]:
 #include <stdio.h>
 void Swap(int *px, int *py);            /*Protótipo da função*/
 void main ()                            /*Programa principal para teste*/
 {
   int a=1, b=2;
   printf("Valor de a=%d, valor de b=%d\n", a, b);
   Swap(&a, &b);
   printf("Valor de a=%d, valor de b=%d\n", a, b);
 }
 void Swap(int *px, int *py)             /*Definição da função*/
 {
   int temp;
   temp = *px;
   *px = *py;
   *py = temp;
 }

Como o operador & fornece o endereço da variável, &a aponta para a. Na função Swap os parâmetros devem ser declarados como ponteiros e os argumentos são acessados por eles.

Ponteiros e vetores

Há uma forte relação entre ponteiros e vetores.

Na linguagem C uma variável vetor é implementada como uma variável ponteiro.

Quando declaramos um vetor, por exemplo:

 int v[10];

a variável v é "um ponteiro para int", ou int *v. Não aparece um asterisco na declaração porque os colchetes indicam automaticamente que a variável é um ponteiro. A diferença entre as declarações int *v; e int v[10]; é que a última reserva 10 posições de inteiros começando na posição v[0][2].

A variável v guarda o endereço base do vetor, que é o endereço do dado armazenado na posição v[0] do vetor. Isto é equivalente a definir um ponteiro, por exemplo pv e atribuir a ele o endereço de v[0]:

 pv=&v[0]

Quando incrementamos um ponteiro ele passa a apontar para o próximo valor do mesmo tipo para o qual o ponteiro aponta. Se você incrementa um ponteiro char* ele anda 1 byte na memória, se você incrementa um ponteiro int* ele anda 2 bytes na memória.

No caso de vetores, pode-se acesssar os valores dos dados armazenados no vetor utilizando ponteiros.

Equivalência entre índices de vetores e ponteiros
Suponha que você defina uma variável i como índice para acessar os valores em um vetor v, logo:
 v[i]
é equivalente a utilizar o ponteiro
 *(v + i)
Exemplo:
 #include <stdio.h>
 void main ()
 {
   int v[10]={1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
   printf("O terceiro elemento do vetor é: %d\n", v[2]);
   printf("O quarto elemento do vetor é: %d\n", *(v+3));
 }
Diferença entre o nome de um vetor e um ponteiro
Um ponteiro é uma variável, por exemplo, se pv é um ponteiro e v é um vetor, pv=v e pv++ são operações válidas. Entretanto, o nome do vetor não é uma variável, portanto, a operação v++ é ilegal.

Ponteiros e strings

Como os strings são vetores de caracteres, cujos caracteres podem ser acessados por índices, o uso de ponteiros com strings é equivalente ao uso de ponteiros com vetores.

Função Strlen com ponteiros
 #include <stdio.h>
 int Strlen(char *s);
 void main ()
 {
   char c[50]="Brasil";
   int len;
   len = Strlen(c);     /*Argumento é um ponteiro para a string c*/
   printf("Comprimento da string: %d\n", len);
 }
 int Strlen(char *s)
 {
   int i;
   for (i=0; *s != '\0'; s++)
      i++;
   return (i);
 }
Note que o ponteiro para a string c (equivalente a &v[0]) é passado como argumento para a função Strlen, a qual é copiada para o parâmetro *s. Portanto, internamente a função é possível incrementar a variável ponteiro s com s++.
Função Strcat com poteiros
Recebe duas strings como parâmetros e concatena as strings na primeira.
#include <stdio.h>
void Strcat(char *s1, char *s2);
void main ()
{
  char string1[20]="Brasil", string2[20]="2014";
  Strcat(string1, string2); /*Os argumentos são ponteiros para as strings*/
  printf("Strings concatenadas: %s\n", string1);
}
void Strcat(char *s1, char *s2)
{
  for (; *s1 != '\0'; s1++)
     ;
  for (; *s2 != '\0'; *s1++=*s2++)
     ;
}
No segundo for o valor apontado por s1 é igualado ao apontado por s2 e depois os ponteiros s1 e s2 são incrementados.

Referências

  1. 1,0 1,1 KERNIGHAN, B.W.; RITCHIE, D.M. The C Programming Language, Prentice Hall, 2o ed. 1978.
  2. 2,0 2,1 TENENBAUM, Aaron M.; LANGSAM, Yedidyah; AUGENSTEIN, Moshe. Estruturas de dados usando C. Makron Books, 1995.

--Evandro.cantu (discussão) 10h31min de 12 de junho de 2014 (BRT)