位移枚举
一、枚举的定义
1.1 普通枚举的定义
我们使用到的普通枚举,定义如下
/*第一种定义方式*/
typedef enum{
QWMDemoTypeTop,
QWMDemoTypeBottom
}QWMDemoType;
/*第二种定义方式*/
typedef NS_ENUM(NSInteger,QWMType) {
QWMTypeTop,
QWMTypeBottom
};
1.2 位移枚举的定义
定义如下
//第三种枚举 ,位移枚举
//一个参数可以传递多个值
//如果是位移枚举,观察第一个枚举值,如果该枚举值!=0 那么可以默认传0做参数,如果传0做参数,那么效率最高
typedef NS_OPTIONS(NSInteger, QWMActionType){
//第三种枚举 ,位移枚举
//一个参数可以传递多个值
//如果是位移枚举,观察第一个枚举值,如果该枚举值!=0 那么可以默认传0做参数,如果传0做参数,那么效率最高
typedef NS_OPTIONS(NSInteger, QWMActionType){
QWMActionTypeTop = 1<<0 , // 1 代表1右移0位 ...00000001(二进制)
QWMActionTypeBottom = 1<<1 , // 2 代表1右移1位 ...00000010(二进制)
QWMActionTypeLeft = 1<<2 , // 4 代表1右移2位 ...00000100(二进制)
QWMActionTypeRight = 1<<3 // 8 代表1右移3位 ...00001000(二进制)
};
二、右移、左移、位与、位或运算
2.1 二进制
我们计算机所能识别的是二进制,当时我们我们现实中使用的是十进制。这个可以看
2.2 右移和左移
为了看着我们方便讨论,我们只讨论一个字节也就是8位二进制,这样我们更直观。
现在我们有十进制的数 1 ,我们现在来通过右移和左移来讨论一把。
1 = 00000001B 十进制 1 等于二进制的 1 这里为了我们讨论方便,所以加上了前面的0.
“<<” 这个符号代码左移,1<<2 这个就是代表我们 把1这个数据左移2位。这里的移动的位数是以二进制为准的。
那么现在回到我们的上面的 00000001B 这个数据上来。
1 << 0 (00000001B << 0) —> 其实就是没有移动,那么就是 1 = 00000001B
1 << 1 (00000001B << 1) —> 向左移动一位,那么数据就变成了 00000010B = 2
同理下下
1 << 2 (00000001B << 2) —> 00000001B << 2 = 00000100B = 4
1 << 3 (00000001B << 3) —> 00000001B << 3 = 00001000B = 8
1 << 4 (00000001B << 4) —> 00000001B << 4 = 00010000B = 16
1 << 5 (00000001B << 5) —> 00000001B << 5 = 00100000B = 32
1 << 6 (00000001B << 6) —> 00000001B << 6 = 01000000B = 64
1 << 7 (00000001B << 7) —> 00000001B << 7 = 10000000B = 128
1 << 8 (00000001B << 8) —> 00000001B << 8 = 00000000B = 0
下面我们来讨论 右移(“>>”代表右移),其实道理是一样的,好的,那么我们来看一个数据 128 这个数据。
128 >> 1 (00000001B >> 1) —> 向右移动一位,那么数据就变成了 01000000B = 64
同理如下
128 << 2 (10000000B << 2) —> 10000000B << 2 = 00100000B = 32
128 << 3 (10000000B << 3) —> 10000000B << 3 = 00010000B = 16
128 << 4 (10000000B << 4) —> 10000000B << 4 = 00001000B = 8
128 << 5 (10000000B << 5) —> 10000000B << 5 = 00000100B = 4
128 << 6 (10000000B << 6) —> 10000000B << 6 = 00000010B = 2
128 << 7 (10000000B << 7) —> 10000000B << 7 = 00000001B = 1
128 << 8 (10000000B << 8) —> 10000000B << 8 = 00000000B = 0
2.3 位与 和 位或
位与(&) 和 位或(|) 中的位都是针对二进制的。其中:
位与
位与 我们可以把它看做是 位相乘,特点就是只有两个都是1那么才会是1,不然都是0。如下
我们取两个数据 1(00000001B) 和 2(00000010B) 来计算一把
0 0 0 0 0 0 0 1 B = 1
&
0 0 0 0 0 0 1 0 B = 2
-----------
0 0 0 0 0 0 0 0 B = 0
上面这个原酸中,我们发现,第一个数据 1 和第二个数据 2 与运算的时候,我们可以看作是 位上面相乘。
两个数据的第一位数据分析: 1 * 0 = 0,所以为结果第一位为 0
两个数据的第二位数据分析: 0 * 1 = 0,所以为结果第二位为 0
。。。。
最后我们得到了数据 就是 00000000B = 0。
下面我们再来看一组数据 1(00000001B) 和 7(00000111B)
0 0 0 0 0 0 0 1 B = 1
&
0 0 0 0 0 1 1 1 B = 7
-----------
0 0 0 0 0 0 0 1 B = 1
两个数据的第一位数据分析: 1 * 1 = 1,所以为结果第一位为 1
两个数据的第二位数据分析: 0 * 1 = 0,所以为结果第二位为 0
。。。
最后我们得到了数据 就是 00000001B = 1。
位或
位或(|) 特点是只要其中一个为 1 ,那二个结果就为1,或者说,只要两个不是不全为0,就是1
下面我们取 9(0 0 0 0 1 0 0 1 B )和 7(0 0 0 0 0 1 1 1 B )来运算一把
0 0 0 0 1 0 0 1 B = 9
|
0 0 0 0 0 1 1 1 B = 7
-----------
0 0 0 0 1 1 1 1 B = 15
三、位移枚举的位与、位或分析
我们现在使用,我们上面提到的 位移枚举,如下
typedef NS_OPTIONS(NSInteger, QWMActionType){
QWMActionTypeTop = 1<<0 , // 1 代表1右移0位 ...00000001(二进制)
QWMActionTypeBottom = 1<<1 , // 2 代表1右移1位 ...00000010(二进制)
QWMActionTypeLeft = 1<<2 , // 4 代表1右移2位 ...00000100(二进制)
QWMActionTypeRight = 1<<3 // 8 代表1右移3位 ...00001000(二进制)
};
下面我们只讨论 最低的一个字节。
我们现在想拥有 QWMActionTypeTop 和 QWMActionTypeBottom
的功能,
那么怎么处理,也即是我们需要二者都存在,这个不就是我们所说的 位或 吗?
于是我们就有
(QWMActionTypeTop | QWMActionTypeBottom)-->( 00000001B | 00000010B) = (00000011B)=3
好的,这样我们就是实现了这个功能。
现在我们有个需求是,别人给我们传递了 一个值过来,我们想知道,它里面有没有有没有
QWMActionTypeTop这个功能呢,其实就是通过运算以后得到有没有 QWMActionTypeTop这个值,
这个不是就是我们说的 位与 吗? 假设我们传递过来了一个值 5(00000101B),那么我们如下操作
00000101B & QWMActionTypeTop ---> 00000101B & 00000001B = 00000001B = QWMActionTypeTop
通过验证我们发现 5 有 QWMActionTypeTop这个功能。
==注意:为什么我们在定义枚举值得时候,使用的只是数据,只有一个位数上有1的,而不是多个位数上有1的呢? 这其实为了避免,位与、位或的时候产生枚举值之间的污染==
四、示例代码
//
// ViewController.m
// 03_UIView90_位移枚举
//
// Created by 杞文明 on 17/9/9.
// Copyright © 2017年 杞文明. All rights reserved.
//
#import "ViewController.h"
/*第一种定义方式*/
typedef enum{
QWMDemoTypeTop,
QWMDemoTypeBottom
}QWMDemoType;
/*第二种定义方式*/
typedef NS_ENUM(NSInteger,QWMType) {
QWMTypeTop,
QWMTypeBottom
};
//第三种枚举 ,位移枚举
//一个参数可以传递多个值
//如果是位移枚举,观察第一个枚举值,如果该枚举值!=0 那么可以默认传0做参数,如果传0做参数,那么效率最高
typedef NS_OPTIONS(NSInteger, QWMActionType){
QWMActionTypeTop = 1<<0 , // 1 代表1右移0位 ...00000001(二进制)
QWMActionTypeBottom = 1<<1 , // 2 代表1右移1位 ...00000010(二进制)
QWMActionTypeLeft = 1<<2 , // 4 代表1右移2位 ...00000100(二进制)
QWMActionTypeRight = 1<<3 // 8 代表1右移3位 ...00001000(二进制)
};
@interface ViewController ()
@end
@implementation ViewController
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self test: QWMActionTypeRight | QWMActionTypeLeft ];
}
-(void)test:(QWMActionType)type{
NSLog(@"%zd",type);
if (type & QWMActionTypeTop) {
NSLog(@"向上---%zd",type & QWMActionTypeTop);
}
if (type & QWMActionTypeRight) {
NSLog(@"向右---%zd",type & QWMActionTypeRight);
}
if (type & QWMActionTypeBottom) {
NSLog(@"向下---%zd",type & QWMActionTypeBottom);
}
if (type & QWMActionTypeLeft) {
NSLog(@"向左---%zd",type & QWMActionTypeLeft);
}
}
@end
五、运行结果
2017-09-10 00:19:00.947 03_UIView90_位移枚举[24230:104789] 12
2017-09-10 00:19:00.947 03_UIView90_位移枚举[24230:104789] 向右---8
2017-09-10 00:19:00.948 03_UIView90_位移枚举[24230:104789] 向左---4