Conversão de decimal para binário em C.

Software e Hardware para uC PIC

Moderadores: andre_luis, 51, guest2003, Renie

Mensagempor RobL » 02 Ago 2008 20:42

Desculpe-me o excesso de "enter" entre linhas.
RobL
Dword
 
Mensagens: 1546
Registrado em: 20 Fev 2007 17:56

Mensagempor fabio_pic » 04 Ago 2008 09:14

Robl,

Obrigado pela ajuda mas ainda não entendo bem essa história de ponteiros, &, etc... Se puder dar um exemplo em C pro Pic ficaria agradecido.

Abraços,
Fábio.
fabio_pic
Nibble
 
Mensagens: 81
Registrado em: 03 Set 2007 09:04
Localização: Rio de Janeiro

Mensagempor joao » 04 Ago 2008 10:49

Vou tentar explicar sobre ponteiros:

Explicação GERAL:
a sua memória é composta de duas partes essenciais: a posição da memória e o valor que ela armazena. Uma frase do tipo HELLO WORLD, não ocupa apenas 1 posição de memória, pois cada letra ocupa uma posição de memória. Ai é que entra os ponteiros. Os ponteiros conseguem "andar" na posição de memória e te retornar o valor que ele está apontando. No exemplo acima:
char *teste = "Hello World" representa isso na memória:

Código: Selecionar todos
H   E   L   L    O       W   O    R   L   D   \0
1   2   3   4    5   6   7    8    9  10  11  12
#


A variável teste, por ser um ponteiro está apontando para a primeira posicao da memória que é aonde está o #. Se vc fizer
teste++;

o # irá para 2, uma vez que teste é o ponteiro e vc está incrementando o ponteiro. Note que a variavel que ele armazena continua a mesma. Agora se vc fizer isso:
*teste++;

Vc está dizendo que o valor que está na posição de memória é que tem que ser incrementada. Como teste está na posição 2, a letra E irá mudar para F(Veja a tabela ASCII para isso).

OBS: Toda frase em C/C++ deve terminar com \0, que é adicionado automaticamente na maioria dos casos.

Vc tem isso em C:

INICIALIZACAO:
------------------------------
int *A; --> Vc até agora só disse que A é um ponteiro, mas nao sabe para aonde está apontando. Na verdade A está apontando para lixo de memória. E o que ela está armazenando é lixo!

int *A = 0X0001 --> Vc está inicializando o ponteiro A com uma posicao. Isso quer dizer que A está apontando para a posicao de memoria 0x0001. E o que ela está armazenando é lixo!

int B --> Aqui vc está dizendo que quer uma variavel B. Isso quer dizer que o ponteiro da posicao de memória dela é automaticamente criado e vc não precisa se preocupar com isso. POrém, o valor que ela está armazenando é lixo!

int B = 0x0001 --> Esse parece igual aos outros, não é? Mas neste caso é o único que o valor armazenado está sendo setado! o valor é 0x0001. E a posição de memória?!?!?! Ela é automaticamente criada e vc não precisa se preocupar com isso. Entendeu que aqui, o valor passado vai para a posição de memória enquanto que nos segundo exemplo vc está passando o endereço da memória? Novamente neste caso a posição de memória foi criada automaticamente.

USO:
-------
Então temos que a variável A é um ponteiro e a variável B não é ponteiro. OK?

printf("%x", A); --> Aqui, se usarmos o segundo método de inicialização, teríamos 0x0001 no resultado do printf. E se usásemos a primeira inicialização? Teríamos lixo! O que é lixo? é um valor qualquer, como por exemplo 0x45D87. O que mostramos aqui é que A, por ser um ponteiro, retorna a posicao do ponteiro quando usamos ela apenas (A).

printf("%x", *A); --> Agora colocamos um *, que significa que queremos ler o que tem na posicao de memoria da variavel A. Nas duas inicializações teríamos LIXO! Porque? Porque nào passamos nenhum valor para A, apenas inicializamos o ponteiro dela. Então como fazemos para passar um valor para ela? Simplesmente fazemos *A = 0X2345;
E se fizermos A = 0x2345? Dá na mesma? NÃO! Porque isso estará mudando a posição de memória de A que agora estará apontando para 0x2345.

printf("%x", B); --> Lembra que B é uma variavél apenas, certo? Então, isso irá mostra o valor que B está armazenando. Se usarmos a quarta inicialização, teremos 0x0001.

printf("%x", *B); --> Isso vai dar error, porque B não é ponteiro, então não pode usar o * na frente dele. Para isso a gente apenas usa a variável B, que nem mostrado acima.
Tá mas ainda quero ver a posição de memória de B, é possível? Claro! é só fazer printf("%x", &B); O & mostra a posição de memória de B!


OUTROS COMANDOS LEGAIS:
----------------
Ainda usando A E B de cima:

Passar endereço de memória:
A = &B; --> Isso quer dizer que A e B estão apontando para o mesmo lugar. Ou seja, se eu mudar o valor da posicao de memoria de A, usando o *A, vou estar mudando o o valor de B. Exemplo:
int B = 0x0001; --> Iniciei B com valor de 0x0001.
int *A = &B; --> Aqui iniciei um ponteiro A com o endereço do ponteiro de B
* A = 0x0003; --> A posicao de memória de A recebeu 0x0003;
printf("%x", B); --> O valor vai ser 0x0003, uma vez que a linha de cima mudou o valor de B;

Incrementando ou descrementando:
Usamos o ++ e o -- para isso:
int B = 1; -->Valor de B é 1
B++; --> Valor de B é 2 agora

Mas para ponteiro? O que acontece?
int *A = 0x0001; --> Posicao de memória de A é 0x0001. O valor que essa posicao guarda eu nao tenho nem idéia de qual é! é lixo!
A++; --> Aqui ele incrementa o ponteiro da posicao de memória! ou seja, vc está apontando para 0x0002!



Por fim, vou explicar sobre a nossa string de character!
Quando fazemos isso:
char *teste = "ISTO É UM TESTE!!!";
Nós não sabemos aonde gravamos o teste, mas sabemos que teste está apontando para o começo da string.
Como assim?
Isso significa que quando fazemos um
printf("%s", teste);
Estamos passando o endereço inicial da string. O %s irá mostrar até achar um \0.(Entendeu porque temos automaticamente um \0 na maioria dos casos?)
internamente, o printf faz algo + - assim:
Código: Selecionar todos
char *texto = parametro; --> Pega o endereço de parametro1(teste no nosso caso);
while(*teste != '\0')  --> Verifica se a variavel é \0 e para dai.
{
     printf("%c", *teste);  --> imprime apenas aquele caracter
     teste++;   --> Incrementa o ponteiro para testar o proximo caracter
}




CUIDADOS!!!!!
---------------
se vc tiver isso:
int *A = 0x0001; --> O endereço de memória de A é 0x0001
int *B = A; --> B tem o mesmo endereço de memória de A
A = 0x0003 --> Mudei o endereço de A é mudado para 0x0003

Somente B agora sabe como pegar novamente o valor de A, pois B ainda tem o endereço de A, que é 0x0001. Quer um exemplo prático?

Código: Selecionar todos
char *A = "TESTE123" ;
char *B = A;

while (*A != '\0')
{
     A++;
}
printf("A variavel A tem %d caracteres!", A - B);

Explicacao: A variavel A PERDEU o seu ponteiro inicial, uma vez que eu fiz A++ e o ponteiro andou. Mas a variavel B salvou a posicao inicial de A. Então, apenas fazendo uma subtracao de A com B, sabemos a quantidade de elementos que tem neste vetor.

Acho que isso.
Desculpa se foi longa a explicação, mas tava vendo algumas coisas chatas aqui no trampo e isso me deixou mais relaxado para continuar a trabalhar agora!
:)

[]'s
Avatar do usuário
joao
Byte
 
Mensagens: 463
Registrado em: 17 Out 2006 08:21

Mensagempor ze » 04 Ago 2008 11:29

olá professor joão. quando tiver mais coisa xata pra fazer dá + uma relaxada xpricano pra nós (mim) seu ponto de vista sobre struct e union. pra mim ainda é um bicho meio que papão.
gracias a lot!!!!
Avatar do usuário
ze
Dword
 
Mensagens: 1655
Registrado em: 05 Jun 2007 14:32

Mensagempor joao » 04 Ago 2008 11:35

hahahaha

O jeito é torcer que o meu chefe não acesse esse forum!
:)

[]'s
Avatar do usuário
joao
Byte
 
Mensagens: 463
Registrado em: 17 Out 2006 08:21

Mensagempor fabio_pic » 05 Ago 2008 08:57

João,

Após alguns dias lendo e relendo o texto cheguei a uma conclusão. Agora acho que aprendi esse negócio de ponteiros. Rsrsrsrsrs
A exlicação está muito boa !!!
Mas tenho algumas dúvidas:

1 - Qual a diferença entre * e &? Parece que o primerio "cria"
o ponteiro e o segundo "lê" o ponteiro.

2 - O tamanho máximo do ponteiro é o tamanho da memória?

3 - Andei procurando material que explicasse melhor a utilização do printf e sempre acho esse comando amarrado à comuinicação serial. Só que, como nos seus exemplos, vi que ele é utilizado, por exemplo, pra LCDs, etc.... Seria muito pedir uma palhinha sobre o comando? Você tem algum material mais detalhado? Nunca vi o resultado do printf sendo guardado em uma variável, por exemplo. Daí a confusão...

Obrigado pela aula de ponteiros.
Fábio.
fabio_pic
Nibble
 
Mensagens: 81
Registrado em: 03 Set 2007 09:04
Localização: Rio de Janeiro

Mensagempor joao » 05 Ago 2008 09:59

Ola Fabio,

Acho que alguém aqui vai poder lhe explicar mais sobre a terceira pergunta, porque faz tempo que não tenho tempo para mexer com o mikroC. Por sinal, a maioria das coisas aqui são para C usado no windows, mas entendendo isso, vc entende o do MikroC, pq são iguais.

1 - Lembre-se sempre que um ponteiro int é diferente de um int! ou seja, se vc criar com * vc está criando um ponteiro. Logo,
int *A; // Para ler a posicao do ponteiro: A
// Para ler o valor da posicao do ponteiro: *A

int B; // Para ler a posicao do ponteiro: &B
// Para ler o valor da posicao do ponteiro: B

Por isso que quando fazemos o comando abaixo é que vai funcionar:
A = &B;
Porque A é um ponteiro e &B retorna um ponteiro.
Agora, se fizer:
A = B;
Não rola, porque vc vai estar passando o valor de B para o ponteiro de A;
Então é só decorar o que eu te mostrei acima ali que vc vai entender bem.

2 - De modo geral, o ponteiro é apenas um ponteiro. Ele poderá ter qualquer valor. Estranho né? Maaaaaaasssss, quando vc tentar usar o ponteiro invalido, a aplicação vai crashear! Por exemplo, vc tem ponteiro até 0x10000 e faz:
A = 0x10001;
Vai funcionar essa linha. Mas quando vc tentar fazer algo do tipo:
*A = 1;
Vai crashear! porque vc invadiu uma área de memória invalida.
Ai é que entra os comandos new e malloc!
eles automaticamente alocam a memória que vc precisa para a sua aplicação. Por exemplo:
int *A;
A =(int*) malloc(3*sizeof(int)); //malloc é usado em C
ou
A = new int(3); //new é usado em C++
O que essas linhas fazem é armazenar uma memória que ele sabe que existe e que está livre. Nos dois exemplos eu pedi uma área de memória de 3 espaços.
Isso significa que eu posso fazer:
A[0] , A[1] e A[2].
Se tentar fazer A[3] vai crashear.


***OBS: NO PIC, eu acho que não crashea, porque vc não tem controle de memória, igual ao computador. Então, vc pode usar o A[3], mas estará usando memória de outra variável ou de outra coisa! Por isso que dai acontece aqueles erros doidos que vc não consegue descobrir o que é! :)

3 - Printf, no windows, serve para mostrar na tela e é isso. Porém, ao invés de mandar para a tela, vc pode usar o sprintf, que grava para um arquivo do tipo Char *.
Mas porque isso? Porque vc pode preparar o texto para mostrar na tela.
Por exemplo, no mikroC:
char *A;
int B = 10;
A = (char*) malloc(20*(char)); //Aloquei 15 posicoes de char!
sprintf(A,"Valor de B:%d",B); //Gravei em A a frase.
LCD_out(1,1,A); //imprimi para LCD.

Viu que eu nem converti a variavel B de int para char? Quem fez isso foi o sprintf! Para isso que ele funciona! Para formatar o texto.

Na verdade, tem várias coisas que depois que vc entende bem sobre ponteiros, vc começa a entender o funcionamento das coisas. Um exemplo é que uma função também está na memória, logo, ela pode ter um ponteiro! :)

Mas tenta entender melhor sobre isso e espero que o povo lhe explique mais sobre como mandar dados para o LCD, da maneira que vc está precisando...

[]'s
Avatar do usuário
joao
Byte
 
Mensagens: 463
Registrado em: 17 Out 2006 08:21

Anterior

Voltar para PIC

Quem está online

Usuários navegando neste fórum: Nenhum usuário registrado e 1 visitante

cron

x