1. switch參數類型
switch參數類型要求是integer type,准確來講,是可以轉換成integer的類型, 這包括所有的C基本數據類型((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;
}
