C 語言中同樣是「把 float 變 int」,`(int32_t)f` 與 `*(int32_t*)&f` 結果截然不同。前者是**值轉換** (語義保留),後者是**內存重解釋** (位模式不變)。混淆兩者會導致嚴重 Bug。
int32_t a;
float b = 123.5f;
a = (int32_t)b; // 值轉換:a = 123 (截斷小數)
a = *(int32_t *)&b; // 內存重解釋:a = 0x42F60000 (IEEE 754 位模式)
| 維度 | 值轉換 (Cast) | 內存重解釋 (Type Punning) |
|---|---|---|
| 語義 | 保留數值近似值 | 保留位模式 |
| 機制 | 編譯器生成轉換指令 (如 `cvttss2si`) | 直接讀取內存位模式 |
| 結果 (123.5f) | `123` | `0x42F60000` (1124073472) |
| 標準合規性 | 完全合規 | C 標準屬 UB (嚴格別名規則),但主流編譯器支持 |
| 典型場景 | 數學計算、縮小類型 | 序列化、網絡字節序、位操作、嵌入式寄存器映射 |
union { float f; int32_t i; } u;
u.f = 123.5f;
int32_t bits = u.i; // 合法
float f = 123.5f;
int32_t bits;
memcpy(&bits, &f, sizeof bits); // 安全、可優化
typedef int32_t alias_int __attribute__((may_alias));
int32_t bits = *(alias_int *)&f; // 告訴編譯器可能別名
**要數值近似 → Cast**;**要位模式 → union/memcpy**。
牢記這句口訣,類型轉換不再踩坑!