Objective-C 繼承 C 語言的整數提升、常規算術轉換規則,並在消息傳遞、集合類、Block 等場景引入額外轉換規則。本文系統梳理從 _Bool 到 long double 的轉換階梯、混合運算求值類型、強制轉換風險與最佳實踐,並針對 NSInteger/CGFloat 等平台相關類型給出建議。
_Bool → char → short → int → long → long long → float → double → long double (枚舉類型視為兼容的整數類型)
混合運算時,**低向高**提升,最終表達式類型為參與運算的最高類型。
float f = 3.14f; int i = 2; long l = 100L; short s = 5; auto result = f * i + l / s; // 類型推導為 float // 步驟:l/s → long/short → long (100/5=20) // f*i → float*int → float (6.28) // float + long → float (26.28f)
long long big = 6666666666LL; // 超出 32 位 int 範圍 int truncated = (int)big; // 實測:-1923267926 (數據丟失,符號翻轉) NSLog(@"big=%lld, truncated=%d", big, truncated);
教訓:窄化轉換(高→低)**必須確保值在目標類型可表示範圍內**,否則行為為實現定義(通常截斷低位),嚴重邏輯錯誤源頭。
int total = 3446, n = 6; float avg1 = total / n; // 整數除法 → 574,再隱式轉 float → 574.0 float avg2 = (float)total / n; // 先轉 float → 574.333... NSLog(@"avg1=%.3f, avg2=%.3f", avg1, avg2);
規則:含浮點運算時,**至少一個操作數**提前轉為浮點類型。
| 類型 | 本質 | 轉換建議 |
|---|---|---|
NSInteger | 32/64 位隨架構 (typedef long 或 int) | 用 NSInteger 接收,避免固定 int/long |
CGFloat | 32/64 位浮點 (float/double) | 格式化用 %f 或 %.2f,避免 %lf |
BOOL | signed char (非 _Bool) | 邏輯判斷直接 if (flag),勿 == YES |
id / 類指針 | 指針 | 轉換用 (__bridge)/__bridge_retained/__bridge_transfer (ARC) |
-Wconversion -Wsign-conversion -Wshorten-64-to-32 捕獲隱式窄化。123L、3.14f、0xFFULL 明確類型。NSUInteger 或 NSInteger,必要時顯式轉換。@(42) → NSNumber,「拆箱」[num intValue],類型安全由運行時保證。