Objective-C 繼承 C 語言的整型提升與常見算術轉換規則,按存儲容量從小到大自動轉換:
_Bool → char → short → enum → int → long → long long → float → double → long double
規則:混合運算時,低類型自動提升為高類型;賦值時,右值隱式轉換為左值類型(可能截斷)。
| 操作數 1 | 操作數 2 | 結果類型 |
|---|---|---|
| char/short/enum | int | int |
| char/short/enum | long | long |
| char/short/enum | long long | long long |
| char/short/enum | float | float |
| char/short/enum | double | double |
| char/short/enum | long double | long double |
| int | long | long |
| int | float | float |
| float | double | double |
float f = 3.14f;
int i = 10;
long l = 100L;
short s = 5;
auto result = f * i + l / s; // 類型推導過程:
// 1. l / s → long / short → long
// 2. f * i → float * int → float
// 3. float + long → float + long → float
// 最終 result 類型為 float
目標類型 值
(類型) 表達式
long long big = 6666666666LL; // 超出 int 範圍
int small = (int)big; // 截斷高位
NSLog(@"big=%lld, small=%d", big, small);
// 輸出: big=6666666666, small=-1923267926 (補碼截斷導致負數)
double precise = 3.141592653589793;
float approx = (float)precise; // 精度從 ~15 位降至 ~7 位
NSLog(@"%.15f vs %.7f", precise, approx);
int neg = -1;
unsigned int u = (unsigned int)neg; // 變為 4294967295 (0xFFFFFFFF)
if (u > 0) NSLog(@"無符號比較陷阱"); // 總是真
int total = 3446;
int n = 6;
// 錯誤:整數除法先執行,截斷小數
float avg1 = total / n; // 574.0
// 正確:強制轉換一個操作數為浮點
float avg2 = (float)total / n; // 574.333333
float avg3 = total / (float)n; // 同樣正確
// 更佳:使用雙精度
double avg4 = (double)total / n;
關鍵:(float)total 先執行轉換,然後浮點除法;優先級高於除法。
// 裝箱
NSNumber *numInt = @42;
NSNumber *numFloat = @3.14f;
NSNumber *numBool = @YES;
// 拆箱
int i = [numInt intValue];
float f = [numFloat floatValue];
BOOL b = [numBool boolValue];
// 通用拆箱 (需類型匹配)
int i2 = numInt.intValue; // 現代語法
// 數字 → 字符串
NSString *str1 = [NSString stringWithFormat:@"%d", 42];
NSString *str2 = @(3.14).stringValue; // NSNumber 重載
// 字符串 → 數字
int i = [@"123" intValue];
float f = [@"3.14" floatValue];
long long ll = [@"9999999999" longLongValue];
// 掃描器 (更健壯)
NSScanner *scanner = [NSScanner scannerWithString:@" 42 "];
int val;
[scanner scanInt:&val]; // 自動跳過空格,返回 BOOL 成功標誌
// 繼承關係:子類指針 → 父類指針 (安全,隱式)
UIView *view = [[UIButton alloc] init];
// 父類指針 → 子類指針 (需強制,運行時檢查)
UIButton *btn = (UIButton *)view; // 若 view 非 UIButton 會崩潰
// 安全檢查
if ([view isKindOfClass:[UIButton class]]) {
UIButton *btn = (UIButton *)view;
}
// id 類型:可指向任意對象,無需強轉
id obj = @"string";
obj = @42;
| 關鍵字 | 用途 | 所有權語義 |
|---|---|---|
| __bridge | Core Foundation ↔ Objective-C 對象指針轉換 | 不轉移所有權 |
| __bridge_retained | OC → CF,調用者負責 CFRelease | 轉移所有權給 CF |
| __bridge_transfer | CF → OC,ARC 負責 release | 轉移所有權給 ARC |
CFStringRef cfStr = CFStringCreateWithCString(NULL, "hello", kCFStringEncodingUTF8);
// CF → NSString (ARC 管理)
NSString *nsStr = (__bridge_transfer NSString *)cfStr;
// NSString → CF (ARC 仍管理,調用者需 CFRelease)
CFStringRef cfStr2 = (__bridge_retained CFStringRef)nsStr;
// ... 使用 cfStr2 ...
CFRelease(cfStr2);
@42, @3.14f, @YES 自動裝箱(double)a / b 或 a / (double)bif (val > INT_MAX) ...-Wconversion -Wshorten-64-to-32 捕獲隱式截斷