Definí dos variables:
uint8_t a[2];
uint16_t b;
A continuación, quiero usar a
como variable de tipo uint16_t
, por ejemplo
b = (uint16_t)a;
Pero esto está mal! Mis programas no funcionan correctamente con dicho código. Todo está bien, cuando sustituyo b
a uint8_t b[2]
las operaciones elementwise uso.
¿Por qué?
Respuestas:
a
es un puntero a una matriz de bytes. Si lo convierte a uint16_t y se lo asignab
,b
contendrá la dirección de la base de la matriz (donde está almacenada) en SRAM. Si desea tratar los dos bytes de la matriza
como un número entero, use una unión como lo sugiere el usuario 14284, pero tenga en cuenta que la unión representará la matriz de bytes en la ordenación de bytes de memoria de la arquitectura (en AVR eso sería poco -endian, que significa que el byte 0 es el byte menos significativo). La forma de escribir eso en código es:Otra forma de hacer esto sin usar una unión es lanzar
a
a un puntero uint16_t y luego desreferenciarlo así:Si está utilizando el búfer para almacenar datos de Big Endian (por ejemplo, el orden de bytes de la red), entonces deberá intercambiar bytes para utilizar cualquiera de estas técnicas. Una forma de hacerlo sin ramificaciones o variables temporales es:
Por cierto, este no es un AVR o incluso un problema solo incrustado. Nivel de aplicación de red de código escrito para PC normalmente llamadas de llamadas funciones
htonl
,htons
(sede de la red, de 32 y 16 bits variantes) yntohl
,ntohs
(red de acogida, de 32 y 16 bits variantes), cuyo objetivo son las implementaciones de la arquitectura depende de si se intercambie los bytes o no (bajo el supuesto de que los bytes transmitidos 'en el cable' siempre son big-endian cuando forman parte de palabras de varios bytes).fuente
a
' por sí sola es un puntero.-fno-strict-aliasing
.Si su intención es concatenar las dos variables de 8 bits en una variable de 16 bits, use a
union
. Si desea convertir un solo miembroa
enb
, especifique qué elemento de la matriz desea usar.fuente
En su código, está lanzando solo el puntero a la matriz.
Necesita emitir el valor señalado por
a
.Nunca utilicé AVR, pero si está trabajando con una arquitectura de 16 bits, debe asegurarse de que a esté alineada por palabras. No hacerlo puede dar lugar a una excepción.
fuente
Cada miembro de a es un número de 8 bits. No puede contener nada más grande. Echándola a 16 bits no hace nada a una . Simplemente extrae cualquier valor que a pueda ser capaz de contener, y lo convierte a 16 bits para que coincida con el formato de b cuando el valor se almacena allí.
Ni siquiera se refirió a un miembro de a . Debe usar un [0] o un [1] (¡y no un [2]!). Si usa un solo, solo obtiene la dirección del mismo. (Buena captura, Bruno).
La declaración de un a ser una matriz de dos números de 8 bits no significa que sea un número de 16 bits, tampoco. Puede hacer algunas cosas mediante programación para almacenar y recuperar valores de 16 bits utilizando secuencias de 8 bits, pero no de la forma en que estaba pensando.
fuente
Si desea convertir los bytes en
a
un valor de 16 bits y la representación es little endian (los 8 bits inferiores del valor vienen en el primer byte), hagaPara una representación big-endian hacer
Evite usar moldes de puntero o uniones para hacer esto, ya que eso conduce a problemas de portabilidad.
fuente