面试题答案
一键面试在Objective-C中,位运算可以有效优化标志位判断场景下的代码性能。
代码示例
// 定义标志位
typedef NS_OPTIONS(NSUInteger, MyFlags) {
MyFlagNone = 0,
MyFlagOne = 1 << 0,
MyFlagTwo = 1 << 1,
MyFlagThree = 1 << 2
};
// 假设某个对象有这些标志位属性
@interface MyObject : NSObject
@property (nonatomic, assign) MyFlags flags;
@end
@implementation MyObject
// 判断是否包含某个标志位
- (BOOL)hasFlag:(MyFlags)flag {
return (self.flags & flag) == flag;
}
// 设置某个标志位
- (void)setFlag:(MyFlags)flag {
self.flags |= flag;
}
// 移除某个标志位
- (void)removeFlag:(MyFlags)flag {
self.flags &= ~flag;
}
@end
原理解释
- 标志位定义:使用
NS_OPTIONS
宏定义标志位,每个标志位是2的幂次方,通过左移操作1 << n
来实现。这样每个标志位在二进制表示中都只有一位是1,其余为0。例如,MyFlagOne
是1
(二进制0001
),MyFlagTwo
是2
(二进制0010
),MyFlagThree
是4
(二进制0100
)。 - 判断标志位:
(self.flags & flag) == flag
这个表达式,&
是按位与操作符。如果self.flags
中包含flag
所对应的标志位,那么按位与的结果就会等于flag
本身,从而判断出对象是否包含该标志位。例如,如果self.flags
是MyFlagOne | MyFlagTwo
(二进制0011
),判断是否有MyFlagTwo
,(0011 & 0010) == 0010
,结果为YES
。 - 设置标志位:
self.flags |= flag
,|
是按位或操作符,它会将self.flags
和flag
对应的二进制位进行或操作,只要有一个为1结果就为1,从而将flag
标志位添加到self.flags
中。例如,如果self.flags
原本是MyFlagOne
(二进制0001
),要设置MyFlagTwo
,0001 | 0010
结果为0011
,即同时包含MyFlagOne
和MyFlagTwo
。 - 移除标志位:
self.flags &= ~flag
,~
是按位取反操作符,先对flag
取反,然后再与self.flags
进行按位与操作。取反后,flag
原来为1的位变为0,这样与self.flags
按位与就会将对应位清零,从而移除flag
标志位。例如,如果self.flags
是MyFlagOne | MyFlagTwo
(二进制0011
),要移除MyFlagTwo
,先对MyFlagTwo
(0010
)取反得1101
,0011 & 1101
结果为0001
,即移除了MyFlagTwo
。
相比使用多个布尔变量来表示不同的标志,位运算可以在一个变量中高效地存储和操作多个标志,减少内存使用并且提升判断和操作的效率。