Eu defini duas variáveis:
uint8_t a[2];
uint16_t b;
Em seguida, quero usar a
como variável do tipo uint16_t
, por exemplo
b = (uint16_t)a;
Mas isso está errado! Meus programas não funcionam corretamente com esse código. Tudo está OK quando eu substituir b
a uint8_t b[2]
e operações de utilização elemento a elemento.
Por quê?
Respostas:
a
é um ponteiro para uma matriz de bytes. Se você o converter em um uint16_t e atribuí-lo ab
, eleb
conterá o endereço da base da matriz (onde está armazenado) na SRAM. Se você deseja tratar os dois bytes da matriza
como um número inteiro, use uma união como sugerido pelo usuário14284, mas lembre-se de que a união representará a matriz de bytes na ordem de bytes da arquitetura da arquitetura (no AVR, seria pouco -endian, que significa byte 0 é o byte menos significativo). A maneira de escrever isso no código é:Outra maneira de fazer isso sem usar uma união é converter
a
em um ponteiro uint16_t e desreferenciar da seguinte forma:Se você estiver usando o buffer para armazenar grandes dados endian (por exemplo, ordem de bytes da rede), precisará trocar de bytes para usar qualquer uma dessas técnicas. Uma maneira de fazer isso sem ramificações ou variáveis temporárias é:
Aliás, isso não é um AVR ou mesmo um problema incorporado. Nível de aplicativo de rede código escrito para PCs normalmente chamadas de funções chamadas
htonl
,htons
(host para rede, de 32 e 16-bit variantes) entohl
,ntohs
(rede de host, de 32 e 16-bit variantes), cuja implementações são alvo dependente da arquitetura para saber se eles troque os bytes ou não (sob a suposição de que os bytes transmitidos 'on the wire' são sempre big-endian quando fazem parte de palavras de vários bytes).fonte
a
' por si só é um ponteiro.-fno-strict-aliasing
.Se sua intenção é concatenar as duas variáveis de 8 bits em uma variável de 16 bits, use a
union
. Se você deseja converter um único membroa
emb
, especifique qual elemento da matriz você deseja usar.fonte
No seu código, você está convertendo apenas o ponteiro para a matriz.
Você precisa converter o valor apontado por
a
.Eu nunca usei o AVR, mas se você estiver trabalhando com uma arquitetura de 16 bits, precisará garantir que a palavra esteja alinhada. Não fazer isso pode resultar em uma exceção.
fonte
Cada membro de a é um número de 8 bits. Não pode conter nada maior. A conversão para 16 bits não faz nada para a . Ele apenas extrai qualquer valor que um possa ser capaz de manter e o converte em 16 bits, para que ele corresponda ao formato de b quando o valor é armazenado lá.
Você nem se referiu a um membro de um . Você deve usar um [0] ou um [1] (e não um [2]!). Se você usa um por si só, apenas obtém o endereço dele. (Boa captura, Bruno).
Declarando um a ser uma matriz de dois números de 8 bits não significa que seja um número de 16 bits, ou. Você pode fazer algumas coisas programaticamente para armazenar e recuperar valores de 16 bits usando sequências de 8 bits, mas não da maneira que estava pensando.
fonte
Se você deseja converter os bytes em
a
um valor de 16 bits, e a representação é little-endian (os 8 bits mais baixos do valor vêm no primeiro byte), façaPara uma representação big endiana, faça
Evite o uso de ponteiros ou uniões para fazer isso, pois isso leva a problemas de portabilidade.
fonte