简体   繁体   English

在 Arm Cortex-M3 上转换为双指针

[英]Casting to double pointer on Arm Cortex-M3

I am using an Arm Cortex-M3 processor.我正在使用 Arm Cortex-M3 处理器。 I receive binary data in an unsigned char array, which must be cast into a suitable variable to be used for further computation:我在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];

This code works on a computer to get the correct value of "f" but it fails on the Cortex-M3.此代码在计算机上工作以获得正确的“f”值,但在 Cortex-M3 上失败。 I understand that does not have an arithmetic unit on the processor, hence doesn't support 64 bit operations;我知道处理器上没有算术单元,因此不支持 64 位操作; but is there a work-around to cast as shown above.但是是否有如上所示的变通方法。

Note that the code below works on the processor;请注意,下面的代码适用于处理器; only the casting shown above fails:只有上面显示的铸造失败:

double d = 9.7;

Also note that 32 bit casts work, as shown below;另请注意,32 位转换可以工作,如下所示; only double or uint64_t fail.只有doubleuint64_t失败。

uint16_t k = *(uint16_t*)&gps[i];

Is there an alternative solution?有替代解决方案吗?

Casting the address of an unsigned char to a pointer to a double – and then using it – is violating strict aliasing rules ;unsigned char的地址转换为指向double的指针——然后使用它——违反了严格的别名规则 more importantly (in your case, as discussed below), it also breaks the required alignment rules for accessing multi-byte (ie double ) data units.更重要的是(在您的情况下,如下所述),它还打破了访问多字节(即double )数据单元所需的对齐规则

Many compilers will warn about this;许多编译器会对此发出警告; clang-cl gives the following for the (double*)&gps[i] expression: clang-cl 为(double*)&gps[i]表达式提供以下内容:

warning : cast from 'unsigned char *' to 'double *' increases required alignment from 1 to 8 [-Wcast-align]警告:从 'unsigned char *' 转换为 'double *' 将所需对齐从 1 增加到 8 [-Wcast-align]

Now, some architectures aren't too fussy about alignment of data types, and the code may (seem to) work on many of those.现在,一些架构对数据类型的对齐并不太挑剔,并且代码可能(似乎)适用于其中的许多。 However, the Cortex-M3 is very fussy about the alignment requirements for multi-byte data types (such as double ).但是,Cortex-M3 对多字节数据类型(例如double )的对齐要求非常挑剔

To remove undefined behaviour, you should use the memcpy function to transfer the component bytes of your gps array into a real double variable, then cast that to a float :要删除未定义的行为,您应该使用memcpy函数将gps数组的组件字节转换为真正的double变量,然后将其转换为float

    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;
    double d; // This will be correctly aligned by the compiler
    memcpy(&d, &gps[i], sizeof(double)); // This doesn't need source alignment
    float f = (float)d; // ... so now, this is a 'safe' cast down to single precision

The memcpy call will use (or generate) code that can access unaligned data safely – even if that means a significant slow-down of the access. memcpy调用将使用(或生成)可以安全访问未对齐数据的代码——即使这意味着访问速度显着减慢。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM