Página 1 de 4
ponteiros como usar e qual a vantagem ??

Enviado:
06 Abr 2010 17:46
por cristian
nao consigo entender este tal de ponteiros sei que
aponta para um endereço da memoria mas pra que realmente serve
nao uso ponteiros nos meus codigos justamente pq nao entendo a eficiencia q isso pode causar

Enviado:
06 Abr 2010 18:05
por fabim
cris.
Temos amisade ja a mais de ano, e te respeito muito..
Mas.
Senhor, tende piedade !!!!!!!!!!!

Enviado:
06 Abr 2010 18:14
por chipselect
usando ponteiro geralmente você consegue código mais rápido, obviamente isso depende de como usar o ponteiro.
Agora imagine que você tenha que manipular e armazenar em memória, uma lista de dados de tipo fixo, mas com quantidades variáveis...
Você consegue fazer isso com vetor enorme, de tamanho fixo, considerando sempre o pior caso (o caso com maior número de dados possíveis). Também é possível fazer isso com uma lista ligada (linked list) que precisa de algo parecido com ponteiro.
A lista ligada tem vantagens e desvantagens em relação a um vetor fixo, basicamente consiste em uma estrutura de dados com um "ponteiro" para a próxima estrutura de dados, e esta lista de dados termina quando você atingir o "nó" ou estrutura de dados cujo ponteiro para o próximo é nulo. A idéia da lista ligada é usar memória conforme for necessário, e não há limitação teórica de quantidade de nós (estruturas de dados) que você armazena na lista.
Outra coisa, todo vetor em C é, na verdade, um ponteiro para o tipo de dados que você está usando.
Exemplo:
int inteiros[10];
inteiros[9] = 0;
int *ptr;
ptr = inteiros;
ptr[9] = 1; //ponteiro sendo tratado como um vetor....
Uma situação de uso é quando você precisa de um vetor que é instanciado dinamicamente em runtime (acho que isso é meio raro nos piczinhos), quando você não sabe com antecedência o tamaho do vetor, dá pra fazer assim:
int *ptr;
ptr = malloc(sizeof(int) * numeroDeInteiros);
ptr[0] = 0;
....
A String em C é, na verdade um vetor de caracteres, logo, quando você declara:
char *s = "teste";
você declarou um vetor de char de 6 posições, cuja última posição é o caracter nulo, e a variável "s" é o ponteiro para a primeira posição do vetor.
Assim, se você fizer:
char c = s[0];
a variável "c" irá conter o caracter 't' (primeira posição do vetor "s")
Isso é meio que o basicão de ponteiro, e há muito mais situações aplicáveis do que descrevi aqui.
Existem desvantagens no uso de ponteiros e linguagem mais modernas, como Java e C# declaram que não tem ponteiros. Na verdade elas não tem ponteiros no sentido que o ANSI C possui de ponteiro, elas esconderam os ponteiros numa camisa de força pro programador topera poder fazer código mais rápido e de maneira mais descuidada, só isso. Já vi NullPointerException em Java e C#, é uma maneira de tratar ponteiros selvagens.
Um item interessante é ponteiro de funções.

Enviado:
06 Abr 2010 18:14
por cmte
Podes dar uma lida aqui:
http://www.mtm.ufsc.br/~azeredo/cursoC/aulas/c600.html
Endereço raiz:
http://www.mtm.ufsc.br/~azeredo/cursoC/c.html
Tinha um outro site legal, mastigadinho, mas se foi com o fim dos serviços do Geocities...
[]´s!

Enviado:
06 Abr 2010 20:28
por cristian
to entende q
- Código: Selecionar todos
void funçao1(char *s1)
{
*s1=20;//alteramos o valor da variavel num atraves do ponteiro
}
funçao(&num);
- Código: Selecionar todos
void funçao1(char s1)
{
s1=20;//nao altera o valor de num so mandamos o valor dele para a funçao
}
funçao(num);
isso é uma das funçoes do ponteiro?

Enviado:
06 Abr 2010 20:51
por Sergio38br

Enviado:
06 Abr 2010 22:50
por tcpipchip
Algum C para Microcontrolador com ALOCAÇÂO DINÂMICA e NÂO ESTÁTICA ?

Enviado:
07 Abr 2010 01:52
por msamsoniuk
na verdade a alocacao dinamica nao eh funcionalidade fornecida pelo compilador, mas sim de bibliotecas de gerenciamento de memoria.
o idela eh comecar fatiando toda a memoria em uma estrutura central de gerenciamento orientada a paginas de tamanho fixo, formando um pool de paginas. estas paginas entao vc distribui para diferentes funcionalidades, por exemplo, um receptor ethernet ira pedir paginas livres para colocar frames ip dentro e entao anexar em queues para firewall, roteamento e transmissao. conforme os frames ip sao transmitidos, as paginas livres sao devolvidos ao pool de buffers e ficam disponiveis para reuso.
em cima disso, se vc achar necessario, vc pode implementar uma biblioteca de mais alto nivel, fornecendo malloc, realloc, calloc e free a partir do seu pool de paginas. quando vc chama malloc, por exemplo, vc vai pegar uma pagina livre e fatiar ela conforme o q vc precisa. digamos que a pagina tem 1KB e vc faz 2 mallocs de 400 bytes e um de 100. dae vc faz mais um de 400, precisa alocar uma nova pagina de 1KB, pq a outra jah esta ocupada... e assim vai
mas na pratica eu soh tenho visto em microcontroador a implementacao do pool de paginas mesmo... implementar malloc jah fica muito rebuscado para processadores com pouca memoria.
tcpipchip escreveu:Algum C para Microcontrolador com ALOCAÇÂO DINÂMICA e NÂO ESTÁTICA ?

Enviado:
07 Abr 2010 08:38
por xultz
Cristian, eu também tenho trauma de ponteiros.
A primeira vez que precisei usar, eu entendi a utilidade. Foi assim.
Imagine que em main você tem algo do tipo:
unsigned char frase[]="Eu odeio ponteiros com todas as minhas forças!!!";
Agora imagine que você tenha uma função que transmite uma frase pela serial, um byte por vez, que é o que o PIC consegue fazer. Como você passa para uma função uma string, como frase ali acima?
Quando você cria uma matriz, ela é um ponteiro para o primeiro byte da matriz. Assim se o protótipo da função transmite_serial fosse
void transmite_serial(unsigned char * primeiro_byte, unsigned char quantidade)
você chamaria a função com
transmite_serial(frase, 49);
Note que minha frase lá em cima tem 49 caracteres.
E a função poderia ser, em portugol
enquanto *primeiro_byte != '/0' faca
registrador_que_envia_pela_serial_que_esqueci_qual_eh = * primeiro_byte;
espera_transmitir;
primeiro_byte++;
fimenquanto
Me fiz entender?

Enviado:
07 Abr 2010 09:08
por fabim
CRISanimal..
Ponteiro né?
Veja isso:
_u char cristiano[] = "um_cara_muito_doido";
Como você sabe, o ansi C no finalzinho aí coloca um null byte...null = 0x00.
Suponha que você quer mandar isso pra uma serial por exemplo, só que foda-se o tamanho da frase, tipo tu não quer ficar contando no dedo o tamanho das consts, ou das variaveis inicializadas na ram..
ói ki legal.
char *ponteiro;
*ponteiro = &cristiano; // pega o endereço de cristiano, e aloca no PONTEIRO, sim ponteiro, flecha, indicação, serve para apontar!!hehe
agora veja.
while(ponteiro!=0){//testa para saber se ja chegou no NULL byte
manda_serial(ponteiro);//manda o byte
*ponteiro++; // aponta para proximo byte
}
ta começando a entender na pratica ?
Agora se eu tivesse contando quantos bytes tinham na const, tipo 20 por exemplo, eu tambem poderia fazer assim.
_u char cristiano[] = "um_cara_muito_doido";
char contador;
for(contador=0; contador<20;contador++){
manda_serial(cristiano[contador]);
}
Se fizer dessa forma, a porcaria da ide, vai fazer o seguinte.
movfw contador
call tabela_cristiano.
tabela_cristiano:
addwf PCL
retlw 'u'
retlw 'm'
etc..
Ta vendo bem isso ? se os pics 18F pra cima tem o sistema de ponteiro via hw <<<< Hardware.. isso mesmo, você consegue usar o INDF FSR"antigos 16F" mais para flash, e tem para ram tambem... Pra que eu vou ficar usando tabela com CALL e casseta a 4 ?
bom, vou tomar café..

Enviado:
07 Abr 2010 09:10
por B-EAGLE
cristian, dê uma lida aqui:
http://www.cplusplus.com/doc/tutorial/pointers/
é o texto mais didático que já vi


Enviado:
07 Abr 2010 09:56
por fabim
corrigindo, é o texto em inglês mais didatico que ele ja viu... hehehe

Enviado:
07 Abr 2010 10:01
por B-EAGLE
fabim escreveu:corrigindo, é o texto em inglês mais didatico que ele ja viu... hehehe
putz vero.... haueahuaehea

Enviado:
07 Abr 2010 11:11
por RobL
Primeiro, nunca perca de vista que só existe bits, byte, words, etc.
Se você já trabalhou com assembly, você sempre trabalhou com "ponteiros"!!!.
Sempre que escreveu na memo foi através da idéia de ponteiro, similar a usar endereçamento indireto, no PIC o registro INDF tem exatamente a idéia de um ponteiro.
A seguir, não vem normalmente nos textos sobre ponteiros.
Em C, ponteiro passa a ser uma abstração. Um programador em C aprende ponteiro sem necessitar saber que vai setar circuitos eletrônicos chamados flip flops (8 deles) formando um byte.
Abaixo vamos concretizar a idéia de ponteiros, o que não é relevante para um programador em C, mas sim para quem não consegue abstrair e quer "ver" o ponteiro em ação:
Em C, quando você declara uma variável, você reserva um espaço na memo (algo real, concreto). Quando você declara um ponteiro, para inteiro, você reservou dois bytes para essa variável (nos microcontroladores de 8 bits)
int *ponteiro ;// reservou dois bytes para o nome ponteiro. O compilador vai reservar automaticamente, mas há como você dizer também onde quer este ponteiro (endereço), mas normalmente isto não tem interesse.
Suponha que o endereço de seu ponteiro, os bytes reservados sejam 0x00 e 0x01 (aqui está os bytes do ponteiro, sem nada dentro) apenas o endereço reservado para ele. Esses bytes é o ponteiro de nome ponteiro.
Agora você precisa colocar nesses dois bytes um endereço de memória ram.
Vamos fazer apontar para o endereço 0x20.
ponteiro = (int *) (0x20) ;// agora o ponteiro aponta para 0x20.
Dentro dos bytes 0x00 e 0x01 está o endereço de 0x20 (0x0020).
Agora vem uma outra abstração (mágica) que é devido a uma rotina nativa do C.
Esta é a mágica, há um "programa" dentro do C que lida com o ponteiro!!!
Quando você fizer:
*ponteiro = 5 ; Um programa nativo do C colocará na memo de endereço 0X20 o valor 0x5 (5d). Agora sim, nada de mágica, é um programa interno do C.
se criar um int:
int val ;
e fizer
val = *ponteiro;
Uma rotina nativa de C, olhará para o endereço 0x00 0x01 pegará o valor que está dentro dele, o byte 0x20, e vai lá na memo 0x20 e pega o valor que está nela, o número 5 e vai associar a val.
Cabe notar que val é outra memo que está em algum endereço. Suponha que val esteja em 0x45.
Olha isso agora:
ponteiro = &val ; // uma rotina nativa dentro do C pegou o valor 0x45 e botou dentro da variável ponteiro, ou seja, o endereço 0x00 0x01 tem o valor 0x0045.
Agora o ponteiro de nome ponteiro está apontando para val na memo 0x45. Dentro da memo 0x45 tem o valor 0x5.
Os bytes 0x00 e0x01 agora tem o valor 0x0045, ou seja ele aponta para 0x45 devido à rotina interna do C. Sempre que mexer com o nome ponteiro a rotina entra em ação se dirigindo para a memo 0x45.
Se fizermos:
printf ("valor do ponteiro %d \n", *ponteiro);
novamente a rotina interna do C para ponteiros vai olhar para o endereço do nome "ponteiro" 0x00 0x01 que está apontando para o endereço 0x45 e pega o valor dentro de 0x45 o número 0x5. Portanto printf vai dar saída o valor 5 decimal.
Se fizermos :
ponteiro++, dentro do endereço 0x00 0x01 estará agora o endereço 0x47, pois um inteiro ocupa 0x45 e 0x46(dois bytes). Se o ponteiro fosse definido como byte (unsigned char), após ponteiro++, apontaria para 0x46 e não para 0x47. Como inteiro o ponteiro vai de 2 em 2 bytes.
Se você definir um ponteiro para byte (unsigned char), você pode percorrer a memo byte por byte. Para que?
Suponha que você queira em um inteiro que tem 2 bytes, pegar um deles, operação essa muito comum.
Define-se um outro ponteiro para byte:
unsigned char *ptr ;
aponto ptr para o endereço da variável val acima :
ptr = &val; // ptr passa a ter o endereço 0x45 (val).
Note prt é um ponteiro para byte. Val é um inteiro com 2 bytes.
ptr está apontando para o endereço 0x45. Exatamente o byte low de val.
Vamos definir:
unsigned char blow, bhi;
blow = *ptr; // pegamos o byte low do inteiro val.
ptr++; // apontou para 0x46 byte hi de val.
bhi = *ptr ; // pegamos o byte alto do inteiro val.
Faça o que quizer com eles agora inclusive um swap.
Sacou???? Com ponteiros você acessa qualquer coisa (objeto). Sem eles
não acessa coisa alguma.
Em funções, passagem por referência, para alterar o valor da variável, em C só com ponteiros.
Pode parecer que ponteiro é só uma questão de comodidade, mas não é. Em C ele é peça fundamental, especialmente em funções. Visto que C é uma função (main) que contém todas as demais, já viu né.
Portanto C sem ponteiros, não é possível!!!
Se deu para entender, lendo os links acima deve ficar mais claro.
Deve ter alguns erros ai em cima, mas aí o pessoal corrige.

Enviado:
07 Abr 2010 12:56
por msamsoniuk
convertendo de portugol para C, ele na verdade queria dizer:
- Código: Selecionar todos
char *p="ponteiros sao legais!";
while(*p) putchar(*p++);
xultz escreveu:Cristian, eu também tenho trauma de ponteiros.
A primeira vez que precisei usar, eu entendi a utilidade. Foi assim.
Imagine que em main você tem algo do tipo:
unsigned char frase[]="Eu odeio ponteiros com todas as minhas forças!!!";
Agora imagine que você tenha uma função que transmite uma frase pela serial, um byte por vez, que é o que o PIC consegue fazer. Como você passa para uma função uma string, como frase ali acima?
Quando você cria uma matriz, ela é um ponteiro para o primeiro byte da matriz. Assim se o protótipo da função transmite_serial fosse
void transmite_serial(unsigned char * primeiro_byte, unsigned char quantidade)
você chamaria a função com
transmite_serial(frase, 49);
Note que minha frase lá em cima tem 49 caracteres.
E a função poderia ser, em portugol
enquanto *primeiro_byte != '/0' faca
registrador_que_envia_pela_serial_que_esqueci_qual_eh = * primeiro_byte;
espera_transmitir;
primeiro_byte++;
fimenquanto
Me fiz entender?