標籤:
1. switch參數類型
switch參數類型要求是integer type,準確來講,是可以轉換成integer的類型, 這包括所有的C基礎資料型別 (Elementary Data Type)((signed/unsigned)char, (short/long signed/unsigned)int, float, double, longlong, bool(C++/objective-c) ),還有枚舉類型,但是不包括字串、結構體、聯合體、對象、函數指標等複雜類型。
其實字串地址指標、對象址指指標等指標,都是可以轉化為UInteger, 因為它們在記憶體中地址都可以理解成unsigned int, 但是為什麼不能使用這些指標作為switch的參數呢? 這是因為這些指標都是動態指定的,每次運行編譯器/程式指定的地址不盡相同,這就會導致case語句會無法判斷是哪一種條件成立,而case後面的條件要求必須是常量;複雜物件的引用往往是利用指標指向的,既然指標都是無法確定其值的,所以複雜物件自然無法作為switch參數了.
e.g. 1 下面這段代碼使用NSString指標作為switch參數,編譯無法通過, 提示Statement requires expression of integer type(‘NSString *__strong‘ invalid)錯誤
NSString *str = [NSString stringWithFormat:@"I am a string."]; NSLog(@"(NSInteger)str=%lx", (NSInteger)str); switch (str) { case (NSInteger)nil: NSLog(@"case nil"); break; default: NSLog(@"case default"); break; }
e.g. 2將switch參數(NSString * )str 修改為(UInteger)str後編譯通過,運行也無錯誤,但是卻沒有執行任何case語句
NSString *str = [NSString stringWithFormat:@"I am a string."]; NSLog(@"(NSInteger)str=%lx", (NSInteger)str); switch ((NSInteger)str) { case (NSInteger)nil: NSLog(@"case nil"); break; default: NSLog(@"case default"); break; }
再次運行發現,兩次運行(NSInteger)str 輸出的地址結果都不一樣
第1次 Log輸出
(NSInteger)str=1001002e0
第2次 Log輸出
(NSInteger)str=1002021c0
這樣自然就匹配不到正確確定的case 語句了。如果想要匹配怎麼辦?那就只能改用if-else語句了,能達到更靈活的效果。
NSString *str = [NSString stringWithFormat:@"I am a string."]; NSString *str2 = str; if (str2 == str) { NSLog(@"\nstr2 == str"); }else{ NSLog(@"\nstr2 != str"); }
Log輸出
str2 == str
2.case 語句塊注意問題
- case 語句是為了匹配switch中的參數的值,所以其條件值必須是常數(const).
- case 作為一個局部語句塊,也能擁有的自己的變數與記憶體空間,那麼在case語句塊內部聲明變數時,應該確保塊內定義的變數,不被塊外使用,否則會導致編譯錯誤(塊外對變數不具有可見度);如果是間接使用,則可能導致運行錯誤(記憶體位址已被釋放,在引用可能指向一個錯誤位置, 也就是所謂的野指標)。
- 如果定義了新的變數,則需要用代碼塊表示符號‘{}‘括起來,否則可能編譯階段報錯。
switch (1) { case 1:{ int a=1; NSLog(@"1. a=%d", a); } NSLog(@"2. a=%d", a); //編譯錯誤 使用未聲明標示符‘a‘ int a=2; //正常通過編譯 NSLog(@"3. a=%d", a); break; case 2: int a=3; //編譯錯誤 非預期運算式 break; }
IOS switch-case知多少