宏定义导致三目运算结果正确
前言:今天记录一下前两天写代码遇到的一个有意思的小问题。这个问题初看很诡异,分析后直击自己知识的浅薄。
首先有两个宏定义,以下程序运行均在手机端运行,也就是两个宏定义结果都是YES
#define kDeviceiPhone [[UIDevice currentDevice].model isEqualToString:@"iPhone"] ? YES : NO
#define kDeviceiPhone [[UIDevice currentDevice].model isEqualToString:@"iPhone"]
这两个宏定义有什么区别吗?如果我用if判断,用一个BOOL类型变量去接收它们,会发现两个宏定义返回的结果是一样的。
为了区分两个宏定义我给它们用两个不同的名字,重新定义一下
#define kDeviceiPhone [[UIDevice currentDevice].model isEqualToString:@"iPhone"] ? YES : NO
#define kDeviceiPhoneDeriected [[UIDevice currentDevice].model isEqualToString:@"iPhone"]
暂且一个叫kDeviceiPhone通过三目运算返回结果,一个叫kDeviceiPhoneDeriected直接就是字符串的isEqualToString返回结果。
接下来就是精彩时刻:
例子一:
你可以猜一下下边代码输出结果
BOOL ret = NO;
if(kDeviceiPhone && ret) {
NSLog(@"=====111111======");
}
我定义了一个变量ret,这个ret初始化为NO。所以宏定义kDeviceiPhone && ret结果是什么呢?如果不加思考肯定直接说结果是NO。但是运行代码就会让你大跌眼镜。
程序运行后进入了if判断,控制台输出了=====111111======
这是什么情况?稍后咱们再分析,继续举栗子。
例子二:
我们再看另一个宏定义是否也会进入这个判断
BOOL ret = NO;
if(kDeviceiPhoneDeriected && ret) {
NSLog(@"+++++22222++++++");
}
理论上宏定义kDeviceiPhoneDeriected返回结果等于kDeviceiPhone的结果,所以跟ret做&&运算,结果应该是一样的,但是这次却不会进入if判断语句,控制台并没有输出任何东西。
我们再看例子三:
BOOL ret = NO;
if(ret && kDeviceiPhone) {
NSLog(@"------3333-------");
}
这次我们把例子1中的kDeviceiPhone与ret的顺序变换了一下,结果呢?你猜到了吗?
控制台没有输出,代码并没有进入if语句。what?
是不是颠覆认知,一个宏定义做&&运算跟前后顺序有关系?
再看例子四:
BOOL ret = NO;
if(ret && kDeviceiPhoneDeriected) {
NSLog(@"+++++4444++++++");
}
这个呢?这次的结果是没有进入到if语句判断,控制台没有输出。还好还好,并没有完全颠覆我的认知。
然后看第五个例子:
BOOL ret = NO;
if((kDeviceiPhone) && ret) {
NSLog(@"=====55555======");
}
这个例子跟第一个好像,但是有点不同,哪里不同呢,宏定义被小括号包住了,这次结果呢?当然这次结果是没有进入if判断语句,控制台没有打印。
下边就开始我们的分析之旅吧。
宏定义的原理是什么呢?
宏定义是用来将一个标识符定义为一个字符串,该标识符被称为宏名,被定义的字符串称为替换文本。
注意:只是简单的替换而已,不要在中间计算结果,一定要替换出表达式之后再算。
好像找到问题所在了。
那么我们把第一个例子替换一下
[[UIDevice currentDevice].model isEqualToString:@"iPhone"] ? YES : NO && NO
我们if语句判断的是不是就上边这个?分析一下为啥结果是YES。首先三目运算符和&&的优先级你应该是知道的吧,原来就是这里。上边代码执行顺序是什么呢?
根据优先级关系,所以代码先执行&&运算,然后执行三目运算。所以第1步,NO&&NO结果为NO, 上边条件语句相当于[[UIDevice currentDevice].model isEqualToString:@"iPhone"] ? YES : NO,然后是第2步,设备型号判断结果返回是正确的,所以三目运算的结果是YES,当然就能进入到if语句判断。
接下来分析第二个例子,第二个就是
[[UIDevice currentDevice].model isEqualToString:@"iPhone"] && NO;
当然结果是NO,毫无疑问。
例子三对应的判断条件是
NO && [[UIDevice currentDevice].model isEqualToString:@"iPhone"] ? YES : NO;
先&&运算结果为NO,然后三目运算返回的结果肯定是NO了。
例子四不再解释,直接看例子五,其实就是加了一个小括号,当然先算括号里的了,返回结果为YES再&&NO,当然是NO了。
其实上边代码无非就是两个知识点,一个是宏定义的替换,一个是三目运算和&&运算的先后顺序。
代码虽然简单,但是想当然的写代码会有太多坑,知识点还是需要吃透才是关键。
你我共勉!!!
本文地址:https://blog.csdn.net/Lu_Ca/article/details/112568043