没有默认情况下的Objective-C枚举“穷举”开关的行为

时间:2019-01-23 00:55:51

标签: c objective-c enums switch-statement

在Swift中,init(rawValue :)系统确保将Int强制转换为枚举会导致有效的枚举大小写或为nil。 在Objective-C中没有这样的安全性,在该安全性中,可以通过强制转换非成员“ rawValue”来创建无效的枚举成员。 typedef NS_ENUM(NSInteger,ExampleEnum){     首先= 0,     第二,     第三, }; +(NSString *)stringForCase:(ExampleEnum)enumCase {     开关(enumCase){         案例优先:返回@“ first”;         第二种情况:返回@“ second”;         案例三:返回@“第三”;     } } +(void)testEnum {     ExampleEnum invalidCase =(ExampleEnum)3; //此“ rawValue”超出范围     NSString * string = [self stringForCase:invalidCase]; //零 } 开启枚举时,如果未处理枚举大小写,编译器将警告您:   枚举值“第三”未在开关中处理 但是,一旦处理完所有情况,就不会出现类似的警告,即枚举的无效成员仍然有可能出现“默认”情况。 在这种情况下的行为是什么? NSString方法似乎返回nil,并且没有观察到崩溃。但是该方法没有任何回报。在什么情况下会自动产生零回报吗? 请注意,“穷举”开关之后的代码语句不会导致通常会生成警告:   代码将永远不会被执行

1 个答案:

答案 0 :(得分:3)

TL; DR ,如果没有大小写匹配,该函数会将控制权返回给调用方,但返回值是 undefined

C / ObjC return语句从根本上做两件事。它使它的值放在特定的位置,以便调用者知道在哪里寻找它。 (该位置由平台/语言ABI定义。)然后将控制移回调用函数(通过从堆栈中弹出地址并跳转到该地址)。

在这种情况下,控制权将直接越过switch的末尾,并且不会执行任何return语句。但是,编译器确实会在方法结束时发出跳转。

(实际上-我不太擅长阅读汇编器,但是-我看到Xcode 10.1为您的代码创建的带有调试注释的汇编器将所有开关情况集中到该方法的单个出口点。如果所有案例比较均未成功,则还 到达出口点。)

但是我们在没有将任何值放入返回寄存器的情况下进行了跳转,这意味着它与任何其他未初始化的值相同-垃圾。您可靠地获得nil的事实可能是由于测试程序的简单性和在调试配置中构建的简单性中的一个或两个。