quinta-feira, 28 de outubro de 2010

IV Semana de Tecnologia das Faculdades COC



Entre os dias 03 e 05 de novembro realizaremos a nossa IV Semana de Tecnologia nas Faculdade COC em Ribeirão Preto / SP.

Acesse o nosso blog para maiores informações e para se inscrever nos minicursos. A  participação nos minicursos é opcional e as vagas são limitadas. A confirmação de inscrição nos minicursos será feita por e-mail.

A presença para alunos será contada nas palestras (uma por dia das 21h30 as 22h50). Acesse o nosso blog e veja os detalhes da programação. Somente o público externo deve inscrever-se para as palestras (vagas limitadas).

sexta-feira, 15 de outubro de 2010

Ponteiros em C

Olá, faz algum tempo que eu não posto nada relacionado a programação, estou muito ocupado ultimamente, trabalhando e estudando, fora os projetos pessoais que invadem a madrugada e finais de semana. Mas hoje, felizmente, tive um tempo para solucionar uma dúvida que pintou aqui na sala.

Os temidos PONTEIROS em C, por ter uma certa experiência em programação, foi fácil assimilar o conceito de endereço de memórias e afins, mas ainda tenho muito o que aprender sobre eles. Então, salve enganos, abaixo vou explicar tudo o que sei sobre esses facilitadores e solucionar algumas dúvidas.

Vamos lá...

 

Introdução

Primeiro, vamos definir o que é ponteiro:

"Em programação, um ponteiro ou apontador é um tipo de dado de uma linguagem de programação cujo valor se refere diretamente a um outro valor alocado em outra área da memória, através de seu endereço. Um ponteiro é uma simples implementação do tipo referência da ciência da computação."
(Wikipedia: http://pt.wikipedia.org/wiki/Ponteiro_(programa%C3%A7%C3%A3o))

Entendido? É simples, imagine da seguinte forma. Você declara uma variável A e atribui a ela o valor de 5.

int a = 5;

Imaginando que você é um super nerd espinhento que decorou os endereços de memória do seu computador, considere que o valor da variável A foi alocado no endereço:

0x10 = a = 5

Agora vamos declarar uma variável que guarda o ondereço de memórias de outras variáveis (isso é um ponteiro):

int *p;

Explicando... Em C, basicamente, quando você insere um asterísco (*) antes do nome da variável ela torna-se um ponteiro, que conterá o endereço de memória de uma variável do mesmo tipo que ela (no exemplo, o ponteiro P necessáriamente terá que apontar para um endereço de memória de uma variável do tipo INTEIRO).

Entendido isso, podemos agora guardar o endereço de memória de A em P, atribuindo A prescedido de um E comercial (&):

p = &a;

Prescedendo um variável qualquer (mesmo ponteiro) com um &, isso faz com que a variável retorne naquele momento seu próprio endereço de memória. Então, se dermos um PRINTF em &a:

// %p é o marcador para mostrar endereços de memória
printf("%p", &a); // exibe: 0x10

 

Trabalhando com Ponteiros

Agora podemos passar para o passo de pegar o valor da variável pelo seu endereço de memória, de uma forma ainda mais simples. Se dermos um PRINTF em P veremos:

printf("%p", p); // exibe: 0x10 (o endereço de memória de A)

E se usarmos o prescedente asterísco (*) em P, veremos:

printf("%i", *p); // exibe: 5 (o valor do endereço de memória, que no caso é o valor da variável A)

Compreendendo tudo isso, podemos definir algumas coisas baseadas em nosso exemplo:

a  = 5
&a = 0x10
p  = &a = 0x10
&p = ao endereço de memória de P, por exemplo, 0x11
*p = a = 5

O que é preciso definir muito bem é, que o ponteiro não se refere a quantidade de memória alocada pela variável (independente do tipo) e sim ao local quem está alocada na memória. Por exemplo, podemos ter a seguinte informação em sua memória:

0x10 = 10 Mb
0x11 = 1 Kb
0x12 = 5 Gb
0x13 = 7 Bytes
0x14 = 100 Tb

 

Vetor é um Ponteiro

Para continuarmos a entender e usar ponteiros, temos que ter em mente que um vetor é um ponteiro (matriz é um pouco diferente). Como assim?!

Um vetor (array para os íntimos), nada mais é que um ponteiro para o endereço de memória da primeira posição do vetor. Por exemplo:

int v[5] = {1, 2, 3, 4, 5};

E assumindo que o programa aloca os seguintes endereços de memória:

0x10 = 1
0x11 = 2
0x12 = 3
0x13 = 4
0x14 = 5

Se dermos um PRINTF em V:

printf("%p", v); // exibe: 0x10
printf("%p", &v[0]); // exibe: 0x10

Então, podemos complementar nossa tabela acima da seguinte forma:

0x10 = v[0] = 1
0x11 = v[1] = 2
0x12 = v[2] = 3
0x13 = v[3] = 4
0x14 = v[4] = 5

 

O Uso do Ponteiro

Em C, se incrementarmos (++) um ponteiro, ele passará a valer o próximo endereço de memória. Por exemplo:

printf("%p", p); // 0x10
p++;
printf("%p", p); // 0x11

Baseado nisso, poder percorrer um vetor incremetando o ponteiro:

int v[5] = {1, 2, 3, 4, 5};

for(i=0; i<5; i++)
{
    printf("V aponta para %p \n", v++);
}

Exibindo:

V aponta para 0x10
V aponta para 0x11
V aponta para 0x12
V aponta para 0x13
V aponta para 0x14

E se quisermos pegar o valor:

int v[5] = {1, 2, 3, 4, 5};

for(i=0; i<5; i++)
{
    printf("V aponta para o valor %i \n", *v++);
}

Exibindo:

V aponta para o valor 1
V aponta para o valor 2
V aponta para o valor 3
V aponta para o valor 4
V aponta para o valor 5

 

Exemplo Prático

Juntando tudo que você provavelmente aprendeu nesse post, tente entender o código abaixo. Está simples e didático:

/*
 * LearningPointers.c
 *
 * @Linux Ubuntu 10.4
 * @IDE Eclipse CDT
 * @Compiler Linux GCC
 *
 *  Created on: Oct 1, 2010
 *      Author: idemax - www.idemax.net
 */

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int x;

    int i=2, *p_int=&i;

    char str[5]="test", *p_str=str; // ou *p=&str

    printf("i\t<-\t%i\n*p_int\t<-\t%i\np_int\t<-\t%p", i, *p_int, p_int);

    printf("\np_str:\t");

    for(x=0; x<5; x++)
    {
        printf("%c", *p_str++); // percorrendo por ponteiro
    }

    return EXIT_SUCCESS;
}

 

Conclusão

Espero ter esclarecido suas dúvidas com ponteiro em C. Qualquer dúvida me mande um e-mail no:
idemax@gmail.com

Até a próxima...

quinta-feira, 14 de outubro de 2010