我使用的是Arm Cortex-M3处理器。我在unsigned char
数组中接收二进制数据,必须将其转换为合适的变量以用于进一步计算:
unsigned char gps[24] = { 0xFA, 0x05, 0x08, 0x00, 0x10, 0x00,0xA4, 0x15, 0x02, 0x42, 0x4D, 0xDF, 0xEB, 0x3F, 0xF6, 0x1A, 0x36, 0xBE, 0xBF, 0x2D, 0xA4, 0x41,
0xAF, 0x1A };
int i = 6;
float f = (float) *(double*)&gps[i];
这段代码在计算机上工作,以获得正确的“f”值,但在Cortex-M3上失败。据我所知,没有一个算术单元的处理器,因此不支持64位操作;但是是否存在如上所示的用于铸造的工作区。
注意下面的代码在处理器上工作;只有上述铸件失效:
double d = 9.7;
还要注意32位强制转换可以工作,如下所示;只有double
或uint64_t
失败。
uint16_t k = *(uint16_t*)&gps[i];
是否有其他解决方案?
1条答案
按热度按时间5anewei61#
将
unsigned char
的地址转换为指向double
的指针-然后 * 使用 * 它-违反了strict aliasing rules;更重要的是(在您的情况下,如下所述),它还破坏了访问多字节所需的alignment rules(即double
)数据单元。许多编译器会对此发出警告; clang-cl为
(double*)&gps[i]
表达式提供了以下内容:警告:从'unsigned char '到'double '的转换将所需的对齐方式从1增加到8 [-Wcast-align]
现在,一些架构对数据类型的对齐并不太挑剔,代码可能(似乎)可以在其中的许多类型上工作。然而,Cortex-M3对alignment requirements for multi-byte data types(例如
double
)非常挑剔。要删除未定义的行为,您应该使用
memcpy
函数将gps
数组的组件字节传输到真实的double
变量中,然后将其转换为float
:memcpy
调用将使用(或生成)可以安全访问未对齐数据的代码--即使这意味着访问速度会显著降低。