我定义了两个变量:
uint8_t a[2];
uint16_t b;
接下来,我想a
用作类型的变量uint16_t
,例如
b = (uint16_t)a;
但这是错误的!我的程序无法正确使用此类代码。当我替换b
为uint8_t b[2]
并使用元素操作时,一切都OK 。
为什么?
我定义了两个变量:
uint8_t a[2];
uint16_t b;
接下来,我想a
用作类型的变量uint16_t
,例如
b = (uint16_t)a;
但这是错误的!我的程序无法正确使用此类代码。当我替换b
为uint8_t b[2]
并使用元素操作时,一切都OK 。
为什么?
Answers:
a
是指向字节数组的指针。如果将其强制转换为uint16_t并将其分配给b
,则b
它将包含SRAM中阵列基址(存储该基址)的地址。如果要将数组的两个字节a
视为整数,请按照user14284的建议使用并集,但请注意,该并集将以体系结构的内存字节顺序表示字节数组(在AVR中将很小) -endian,表示字节0是最低有效字节)。用代码编写的方式是:
union{
uint8_t a[2];
uint16_t b;
} x;
x.b[0] = 0x35;
x.b[1] = 0x4A;
// by virtue of the above two assignments
x.a == 0x4A35 // is true
另一种不使用并集的方法是a
强制转换为uint16_t指针,然后像这样取消引用:
uint8_t a[2] = {0x35, 0x4A};
uint16_t b = *((uint16_t *) a);
b == 0x4A35; // because AVR is little endian
如果使用缓冲区存储大字节序数据(例如,网络字节顺序),则需要进行字节交换以使用这两种技术。没有任何分支或临时变量的一种实现方法是:
uint8_t a[2] = {0x35, 0x4A};
a[0] ^= a[1];
a[1] ^= a[0];
a[0] ^= a[1];
a[0] == 0x4A; // true
a[1] == 0x35; // true
顺便说一下,这不是AVR,甚至不是嵌入式问题。应用级网络代码写入用于PC通常呼叫调用的函数htonl
,htons
(主机到网络,32位和16位的变体)和ntohl
,ntohs
它的实现是目标架构取决于是否(网络到主机,32位和16位的变体),他们是否交换字节(假设“在线”传输的字节在多字节字中时始终为大端)。
a
' 的键是一个指针。
-fno-strict-aliasing
。
在您的代码上,您仅转换了指向数组的指针。
您需要转换由指向的值a
。
b = (uint16_t)*a;
我从未使用过AVR,但是如果您使用的是16位架构,则必须确保a是字对齐的。否则可能会导致异常。