ponteiros como usar e qual a vantagem ??

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

ponteiros como usar e qual a vantagem ??

Mensagempor cristian » 06 Abr 2010 17:46

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
cristian
Word
 
Mensagens: 570
Registrado em: 03 Nov 2006 08:15
Localização: serrinha-ba

Mensagempor fabim » 06 Abr 2010 18:05

cris.

Temos amisade ja a mais de ano, e te respeito muito..

Mas.

Senhor, tende piedade !!!!!!!!!!!
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor chipselect » 06 Abr 2010 18:14

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.
chipselect
Word
 
Mensagens: 744
Registrado em: 16 Out 2006 18:50

Mensagempor cmte » 06 Abr 2010 18:14

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!
cmte
Byte
 
Mensagens: 141
Registrado em: 29 Nov 2006 12:53

Mensagempor cristian » 06 Abr 2010 20:28

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?
cristian
Word
 
Mensagens: 570
Registrado em: 03 Nov 2006 08:15
Localização: serrinha-ba

Mensagempor Sergio38br » 06 Abr 2010 20:51

Avatar do usuário
Sergio38br
Word
 
Mensagens: 759
Registrado em: 22 Nov 2007 13:39
Localização: São Paulo - SP

Mensagempor tcpipchip » 06 Abr 2010 22:50

Algum C para Microcontrolador com ALOCAÇÂO DINÂMICA e NÂO ESTÁTICA ?
Avatar do usuário
tcpipchip
Dword
 
Mensagens: 6560
Registrado em: 11 Out 2006 22:32
Localização: TCPIPCHIPizinho!

Mensagempor msamsoniuk » 07 Abr 2010 01:52

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 ?
#innovation #poweredby #riscv https://github.com/darklife/darkriscv
Avatar do usuário
msamsoniuk
Dword
 
Mensagens: 2935
Registrado em: 13 Out 2006 18:04

Mensagempor xultz » 07 Abr 2010 08:38

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?
98% das vezes estou certo, e não estou nem aí pros outros 3%.
Avatar do usuário
xultz
Dword
 
Mensagens: 3001
Registrado em: 13 Out 2006 18:41
Localização: Curitiba

Mensagempor fabim » 07 Abr 2010 09:08

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é..
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor B-EAGLE » 07 Abr 2010 09:10

cristian, dê uma lida aqui:

http://www.cplusplus.com/doc/tutorial/pointers/


é o texto mais didático que já vi ;)
B-EAGLE
Word
 
Mensagens: 847
Registrado em: 19 Out 2006 14:12
Localização: Campo Grande - MS

Mensagempor fabim » 07 Abr 2010 09:56

B-EAGLE escreveu:cristian, dê uma lida aqui:

http://www.cplusplus.com/doc/tutorial/pointers/


é o texto mais didático que já vi ;)


corrigindo, é o texto em inglês mais didatico que ele ja viu... hehehe
Mano, ve só.
Sou responsável pelo que escrevo!!! E não pelo que você entende !!!
fabim
Dword
 
Mensagens: 5001
Registrado em: 16 Out 2006 10:18
Localização: aqui uái!!!?

Mensagempor B-EAGLE » 07 Abr 2010 10:01

fabim escreveu:
B-EAGLE escreveu:cristian, dê uma lida aqui:

http://www.cplusplus.com/doc/tutorial/pointers/


é o texto mais didático que já vi ;)


corrigindo, é o texto em inglês mais didatico que ele ja viu... hehehe



putz vero.... haueahuaehea
B-EAGLE
Word
 
Mensagens: 847
Registrado em: 19 Out 2006 14:12
Localização: Campo Grande - MS

Mensagempor RobL » 07 Abr 2010 11:11

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.
Editado pela última vez por RobL em 07 Abr 2010 13:01, em um total de 1 vez.
RobL
Dword
 
Mensagens: 1546
Registrado em: 20 Fev 2007 17:56

Mensagempor msamsoniuk » 07 Abr 2010 12:56

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?
#innovation #poweredby #riscv https://github.com/darklife/darkriscv
Avatar do usuário
msamsoniuk
Dword
 
Mensagens: 2935
Registrado em: 13 Out 2006 18:04

Próximo

Voltar para PIC

Quem está online

Usuários navegando neste fórum: Google [Bot] e 1 visitante

x