Bom dia pessoal.

Este  "erro"  da IDE do Arduíno na minha opinião não deveria acontecer.

Descrição do sketck:

Defino 2 variáveis com o tamanho byte e defino 2 valores em hexadecimal.

byte K = 0x49;
byte M = 0x94;

Em seguida imprimo a parte alta da primeira variável 

" Serial.println((K & 0xF0), HEX); "

e imprimo deslocando 4 bits para esquerda a segunda variável 

"  Serial.println((M 4), HEX); "

Como cada variável foi definida como byte (8 bits),

o resultado deveria ser também somente um byte, 

mas o resultado aparece assim

40          primeiro print
940        segundo print      2 bytes ??

Code de texto em anexo.

RV

Exibições: 354

Anexos

Responder esta

Respostas a este tópico

Não deveria, realmente.

Faz falta nessas horas poder ver o arquivo intermediário de compilação, algo como:

https://forum.arduino.cc/index.php?topic=116132.0

Nunca usei isso em Arduino, mas no 8051 quebrava um galhão. Mostrava como comentário a linha em C e depois o que virou em ASM.

Boa tarde Rui, 

Já passei por essa situação também - e é um resultado normal.

Na verdade você esta criando um novo número, quando insere zeros no lado direito (adicionando 4 bits) , usando a função " M > > 4 " bitshift right. No total seu número tem 12 bits. 

https://www.arduino.cc/reference/en/language/structure/bitwise-oper...

Boa tarde José Gustavo Abreu Murta ,

seria normal se a variável não fosse do tamanho byte.

O link que você usou colou mostra operação com variável tamanho  "int".

Neste caso sim, o deslocamento dentro de 16 bits pode conter 12 bits,

mas um deslocamento dentro de 8 bits não pode conter 12 bits.

Em linguagem C, quando usa-se um deslocamento maior que o tamanho da variável,

  os bits  excedentes são descartados.

Exemplo:

byte

 X = 0x5F   -->  0101 1111          X>>4   -->   0000 0101   e 1111 pro lixo pois o espaço

alocado para byte é de somente 8 bits.

RV

boa tarde RV.

    Nota inicial:  pessoal, o símbolo do shift para a esquerda do "C/C++", não aparece de jeito algum no texto aqui do Garagem, e por isso tive que substituir pelas palavras "shift left" nos trechos de código a seguir. Doidices.

    Agora o post em si:

    Conferindo o Arduino CC, vc tem toda razão RV, já que os bits deslocados para a esquerda serão descartados, conforme vemos na figura a seguir:

     Mas aqui entra um coadjuvante que quer ser protagonista: a implementação overload na biblioteca primitiva do Arduino, para qualquer print. Para o tipo "byte", você pode ver essa implementação na figura a seguir:

     Veja que esta é uma das funções overload para o print, especificamente a do "unsigned char", ou seja para o "byte".

     O que ocorre é isto:  apesar de vc estar usando uma variável do tamanho "byte", o "Parser" do Compilador no intuito de simplificar o código, expande a análise e assim copia o seu "(M shift left 4)" para dentro do overload do "print", ou seja, substitui a variável simbólica "b" do print com o "(M shift left 4)". Mas veja que o print definitivo é feito por "outro print' dentro do overload, e isso resulta nisso:

             print ( (unsigned long) (M shift left 4), HEX );

     E este último "print" que efetivamente fará o serviço, faz um casting e converte seu byte para "unsigned long". Bem, daí pra frente você já sabe o que vai acontecer: na impressão final os zeros não significativos serão descartados, mas o "9" do "(0x94 shift left 4)" estará lá firme e forte.

     O motivo de terem feito isso no overload: eles consideraram que ao fazer o "casting" para um tipo maior, não haverá prejuízo para os dígitos do resultado. Mas não perceberam que isto pode descaracterizar o entendimento da variável quando se usa o "". Então podemos afirmar que acaba sendo um "bug", resultante da uma implementação particular da biblioteca primitiva do print, e ocorre quando o "Parser" do Compilador vai "expandir" a expressão para chegar ao código final.

     Detalhe: na implementação da biblioteca primitiva do print, o mesmo casting é também feito para o tipo "word" (o "unsigned int"). E a mesma coisa para os tipos "signed", mas neste caso o casting é feito usando o "long".    

     Espero ter ajudado a elucidar o "mistério".

    Abrçs

    Elcids

Boa noite Sr.  Elcids Chagas,

apesar das obervações do Sr. serem pertinentes, tenho que discordar.

Se observar e usar o code que anexei, o problema não acontece somente no método print.

Ocorre também na instrução "if",

A razão para que eu usasse o método print foi para debug, pois o " if"  não funcionava como eu queria.

Att.

Rui

realmente RV.

     Porém neste caso, o resultado do "if" será sempre uma variável booleana, a qual está desvinculada de tamanhos e dígitos significativos (embora de fato também seja um tipo inteiro, como bem sabemos). Por esse motivo o Compilador GCC ao perceber que toda a expressão é composta apenas por inteiros, ele toma a liberdade de expandir o resultado para o maior tipo inteiro que trabalha (pelo motivo de não haver prejuízo para quaisquer dígitos, como mencionei no post anterior), e acaba tendo o resultado que você visualizou.

     Isto não é uma inconsistência no processamento da linguagem, porque "eles" consideram que você pode estreitar a avaliação usando um "casting" específico, como nisso:

     "(byte) (M shift left 4)"

     O Compilador GCC, assim como tantos outros, está cheio dessas pequenas armadilhas (eu já fui vítima disso também). Mas não somos nós que ditamos como eles funcionam, e sim a comunidade que trabalha nisso.

     Abrçs

     Elcids

Concordo com o Elcids = 

"Mas não somos nós que ditamos como eles funcionam, e sim a comunidade que trabalha nisso"

    Outro caso clássico, e irritante, é quando você faz isso:

//--------------------------------------------------

#define   menos_um   -1

byte  TESTE = menos_um;

//--------------------------------------------------

     neste caso já dá erro em tempo de compilação. Então perguntamos: porque diabos o Compilador não fez o uso apenas dos 8 bits do "-1" (que seria 0xFF)?  ou seja, porque ele não fez um casting automático?

     Ao invés, ele pegou o "-1" como sendo 0xFFFFFFFF (ou seja, usando o "long", 32 bits), por mais absurdo que pareça. Mas por que isto?

     Então a resposta é:  porque "eles" querem que nós façamos isto:

//--------------------------------------------------

#define   menos_um  -1

byte  TESTE =   (byte) menos_um;

//--------------------------------------------------

     Seria apenas pra nos irritar?

     Como diz meu Pai, "é dose", mas temos que engolir (viva Zagalo!!!).

     Abrçs

     Elcids

RSS

© 2024   Criado por Marcelo Rodrigues.   Ativado por

Badges  |  Relatar um incidente  |  Termos de serviço