[英]Casting to double pointer on Arm Cortex-M3
我正在使用 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];
有替代解決方案嗎?
將unsigned char
的地址轉換為指向double
的指針——然后使用它——違反了嚴格的別名規則; 更重要的是(在您的情況下,如下所述),它還打破了訪問多字節(即double
)數據單元所需的對齊規則。
許多編譯器會對此發出警告; clang-cl 為(double*)&gps[i]
表達式提供以下內容:
警告:從 'unsigned char *' 轉換為 'double *' 將所需對齊從 1 增加到 8 [-Wcast-align]
現在,一些架構對數據類型的對齊並不太挑剔,並且代碼可能(似乎)適用於其中的許多。 但是,Cortex-M3 對多字節數據類型(例如double
)的對齊要求非常挑剔。
要刪除未定義的行為,您應該使用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
memcpy
調用將使用(或生成)可以安全訪問未對齊數據的代碼——即使這意味着訪問速度顯着減慢。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.