Wikia

Programação

Páginas vigiadas Mudanças recentes

C/Faq/Ponteiros

< C | Faq

Este artigo faz parte do FAQ para a linguagem C. Para o índice do FAQ, confira C/Faq. Para a linguagem em si, confira C.

Antes de acrescentar dúvidas a este FAQ, confira a Política de FAQ!

Tabela de conteúdo


O que são ponteiros?Editar

Ponteiros são tipos de variáveis destinadas a armazenar endereços de memória. Na linguagem C, ponteiros são normalmente associados a um tipo do dado nativo ou definido pelo usuário, que corresponde ao tipo do dado armazenado na posição de memória para a qual o ponteiro efetivamente aponta.

Abaixo há alguns exemplos de declarações de ponteiros.

int *p_i;    /* p_i é uma variável que provavelmente armazenará o endereço de um dado do tipo "int". */

struct meu_tipo_de_dado_composto *p_mtdc;
             /* p_mtdc é uma variável que provavelmente armazenará o endereço de um dado do tipo
                "struct meu_tipo_de_dado_composto". */

int **p_p_i; /* p_p_i é uma variável que provavelmente armazenará o endereço de um dado do tipo
                "ponteiro que armazena o endereço de um dado do tipo int". */

char (*p_a_c)[5];
             /* p_a_c é uma variável que provavelmente armazenará o endereço de um dado do tipo
                "array de char com cinco posições. */

char *a_p_c[5];
             /* a_p_c é um array de cinco posições de ponteiros que possivelmente terão os endereços
                de dados do tipo "char". */

void *p;     /* p é uma variável que armazena o endereço de qualquer tipo de dados. */

Para que servem ponteiros?Editar

Ponteiros são úteis para diminuir a necessidade de copiar dados de um lugar para outro, em parte por sua capacidade de se tornarem lvalues do tipo do dado para o qual apontam.

Imagine, por exemplo, o caso de uma variável X que receba uma valor inicial dentro de uma função func1(). Suponha que, após ser utilizada por algum tempo nessa função, decida-se usar uma função func2(), que usa o valor atual como base de processamento e retorna um resultado, que será gravado novamente em X, já que o valor antigo não será mais necessário e não se quer desperdiçar memória com a criação de diversas variáveis temporárias do mesmo tipo. O código abaixo seria uma possível implementação de algo deste tipo em C (supondo que o tipo de X seja int).

int func2(int);

void func1(void){
    int X = 0;

    /* Usa X por algum tempo, talvez até alterando seu valor. */

    X = func2(X);  /* Usa o valor atual de X como base de cálculo de func2(), e grava o resultado em X. */

    /* Usa o novo valor de X */
}

int func2(int valor_inicial){
    int result;

    /* Realiza alguma computação baseada em valor_inicial e salva o resultado em result.
       No nosso exemplo, a operação será apenas calcular o dobro do valor. */

    result = 2 * valor_inicial;

    return result;
}

Quando o código acima é compilado, a linha que contém o comando X=func2(X); produz a seguinte seqüência de operações de máquina:

  1. copia o valor atual de X para uma área onde são guardados os parâmetros que serão passados à função func2();
  2. chama func2();
  3. copia o valor armazenado na área de resultados produzidos pela função func2() para a variável X.

Uma vez que X é do tipo int, as operações de cópia antes da chamada de func2() e após tal função ter retornado não parecem um grande problema.

Imagine, porém, um problema semelhante, não com uma variável do tipo int, mas com uma estrutura complexa e que ocupasse vários bytes na memória. Se fosse utilizado o mesmo algoritmo, as operações de cópia que ocorrem antes e depois da chamada a func2() certamente teriam mais impacto sobre o desempenho do programa.

Uma forma de evitar a cópia de dados de um lado para outro é usar apenas variáveis globais, mas isso acabaria com a estruturação e modularidade do programa. Outra forma, mais simples e elegante, é passar apenas o endereço de memória onde se encontra o dado a ser manipulado, a fim de que a função use esse endereço para acessar indiretamente tal dado.

O código acima poderia ser reescrito usando ponteiros da forma como mostrado abaixo.

void func2(int *);

void func1(void){
    int X = 0;

    /* Usa X por algum tempo, talvez até alterando seu valor. */

    func2(&X);  /* Envia o endereço de X a func2(), que poderá usá-lo para ler e alterar seu valor. */

    /* Usa o novo valor de X */
}

void func2(int *p_valor){
    /* Realiza alguma computação baseada no valor inicial, que pode ser obtido a partir do endereço
       fornecido, e salva o resultado na mesma região de memória.  No nosso exemplo, essa computação
       será apenas calcular o dobro do valor inicial. */
    *p_valor = *p_valor * 2;
}

Ponteiros são elementos de baixo nível ou de alto nível?Editar

Em C, ponteiros são um dos elementos de mais baixo nível da linguagem, pois geralmente armazenam diretamente o endereço de memória onde se encontram dados. Isso é útil para muitas coisas -- inclusive a maioria das que fazem com que C seja útil para o desenvolvimento de sistemas operacionais, por exemplo --, mas requer a devida dose de cuidado.

É verdade que ponteiros são uma fonte comum de problemas em programas escritos em C? Se é, qual o motivo?Editar

Sim, muitos dos bugs que acometem programas em C são devidos a maus usos de ponteiros.

Freqüentemente tais problemas são causados por um ou mais dos seguinte motivos:

  • entendimento inadequado sobre o que são ponteiros;
  • entendimento inadequado sobre operações com ponteiros;
  • tentar de-referenciar ponteiros nulos;
  • tentar de-referenciar ponteiros não inicializados;
  • misturar ponteiros para tipos diferentes, de modo que, quando de-referenciados, os dados obtidos não sejam consistentes;
  • usar ponteiros para alocar blocos de memória e esquecer de liberar a memória apontada por esses ponteiros quando tais blocos não são mais necessários;
  • usar ponteiros para alocar blocos de memória e liberar tais blocos, através de seus ponteiros, mais de uma vez;
  • tratar como relativos a alocação dinâmica de memória ponteiros que apontam para outras partes da memória.

void e uma funçao que nao nao retorna nehuma valor exemplo de funcao que retorna um valor inteiro(int): int soma(int x,int y) {

  return x+y;

} a funçao soma retorna a soma de x + y agora um exemplo de funçao que nao retorna nenhum valor ou seja void

void olamundo {

  puts("ola mundo");

} esta funçao nao retornou nenhum valor apenas executou o procedimento dentro dela

Qual é o problema com este código...? (return &p)Editar

int *ponteiro(int n)
{
    int p = n;
    return &p;
}

A variável p é um objeto de escopo função. Funções de escopo de função deixam de existir quando a execução da função finaliza. Assim, o retorno de ponteiro() será um endereço de memória inválido.

Retornar o endereço de uma variável local é "quase sempre" um erro.

Páginas na Programação

Adicionar página
23páginas
nessa wiki
Advertisement | Your ad here

Latest Photos

Adicionar uma Foto
3fotos nessa wiki
Ver mais >

Wiki Atividade recente

Ver mais >

Mais da comunidade Wikia

Wiki aleatória