今天对iOS的枚举和位运算做一下整理,主要内容如下:
1.iOS中的两个枚举类型:NS_OPTIONS,NS_ENUM
2.枚举使用位运算的原因
3.位运算介绍和扩展
一.枚举类型
一般情况下,我们采用C风格的enum关键字可以定义枚举类型。
enum{
UIViewAnimationTransitionNone,
UIViewAnimationTransitionFlipFromLeft,
UIViewAnimationTransitionFlipFromRight,
UIViewAnimationTransitionCurlUp,
UIViewAnimationTransitionCurlDown,
} UIViewAnimationTransition;
//位移操作枚举定义
enum {
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
typedef NSUInteger UIViewAutoresizing;//使用NSUInteger的地方可以使用UIViewAutoresizing,UIViewAutoresizing相当于NSUInteger的一个别名使用,因此一个UIViewAutoresizing的变量可以直接赋值给NSUInteger
枚举值一般是4个字节的int值,在64位系统上是8个字节。
在iOS6和Mac OS 10.8以后Apple引入了两个宏来重新定义这两个枚举类型,实际上是将enum定义和#define合二为一,并且采用不同的宏来从代码角度来区分(下文介绍)。我们可以参考UIKit.Framework的头文件,可以看到大量的枚举定义。
typedef NS_ENUM(NSInteger, UIViewAnimationTransition) {
UIViewAnimationTransitionNone,//默认从0开始
UIViewAnimationTransitionFlipFromLeft,
UIViewAnimationTransitionFlipFromRight,
UIViewAnimationTransitionCurlUp,
UIViewAnimationTransitionCurlDown,
};
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
UIViewAutoresizingNone = 0,
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,
UIViewAutoresizingFlexibleWidth = 1 << 1,
UIViewAutoresizingFlexibleRightMargin = 1 << 2,
UIViewAutoresizingFlexibleTopMargin = 1 << 3,
UIViewAutoresizingFlexibleHeight = 1 << 4,
UIViewAutoresizingFlexibleBottomMargin = 1 << 5
};
#if (__cplusplus && __cplusplus >= 201103L && (__has_extension(cxx_strong_enums) || __has_feature(objc_fixed_enum))) || (!__cplusplus && __has_feature(objc_fixed_enum))
#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type
#if (__cplusplus)
#define NS_OPTIONS(_type, _name) _type _name; enum : _type
#else
#define NS_OPTIONS(_type, _name) enum _name : _type _name; enum _name : _type
#endif
#else
#define NS_ENUM(_type, _name) _type _name; enum
#define NS_OPTIONS(_type, _name) _type _name; enum
#endif
将
typedef NS_ENUM(NSInteger, UIViewAnimationTransition) {
展开得到
typedef enum UIViewAnimationTransition : NSInteger UIViewAnimationTransition;
enum UIViewAnimationTransition : NSInteger {
二.枚举和位运算
从枚举定义来看,NS_ENUM和NS_OPTIONS本质是一样的,而iOS使用两种方式定义的目的是区分使用场景----是否可以"多选".
在系统API中可以看到NS_OPTIONS定义的枚举都采用了位运算作为枚举内容,而NS_ENUM则没有,其原因就是NS_OPTION的枚举值同时使用时(相加)仍具有唯一性,可使用或运算相加进行"多选"操作.位移不同数位得到的枚举数值代表二进制中不同的数位,不同数位相加的结果是唯一的.
多个NS_OPTION的枚举值或运算赋值给结果就如同一个"选项集合"(option),如上代码自适应既可以选择宽度自适应也可以选择高度自适应,各选项之间并不互斥唯一,当使用结果进行判断时,只需要将结果和目标选项进行位与运算,如真则可确认集合中包含了该枚举值.如下:
if (options & SDWebImageDownloaderHighPriority) {
operation.queuePriority = NSOperationQueuePriorityHigh;
}
我们自己在实际使用时,我们仍可以直接定义:
typedef enum : NSInteger {....} UIViewAnimationTransition;
并根据需要是否将枚举值定义为位运算来满足多选需求.
三.位运算介绍
枚举及位运算在编程中的应用
位运算是指按二进制进行的运算。在系统软件中,常常需要处理二进制位的问题。C语言提供了6个位操作。运算符。这些运算符只能用于整型操作数,即只能用于带符号或无符号的char,short,int与long类型。这里只用到“按位与”运算符(&)与右移运算符(>>)。
按位与是指:参加运算的两个数据,按二进制位进行“与”运算。如果两个相应的二进制位都为1,则该位的结果值为1;否则为0。这里的1可以理解为逻辑中的true,0可以理解为逻辑中的false。
右移运算符是用来将一个数的各二进制位右移若干位,移动的位数由右操作数指定(右操作数必须是非负值),移到右端的低位被舍弃,对于无符号数,高位补0。对于有符号数,某些机器将对左边空出的部分用符号位填补(即“算术移位”),而另一些机器则对左边空出的部分用0填补(即“逻辑移位”)。
如果我们想获取二进制代码中某位上的值,可以采用与运算,然后根据其所在位进行右移即可。
例:1.获取15二进制代码中的第四位:
将15与8进行与运算:15&8
1111
1000
1000
将其右移三位得到:0001
2.获取9的第二位:
将9与2进行与运算:1001
0010
0000
将其右移一位得到:0000
编程题目
1.某游戏规则中,甲乙双方每个回合的战斗总是有一方胜利,一方失败。游戏规定:失败的一方要把自己的体力值的1/4加给胜利的一方。例如:如果双方体力值当前都是4,则经过一轮战斗后,双方的体力值会变为:5,3。
现在已知:双方开始时的体力值甲:1000,乙:2000。
假设战斗中,甲乙获胜的概率都是50%
求解:双方经过4个回合的战斗,体力值之差小于1000的理论概率。
解析:双方经过四个回合的战斗,则一共会出现的情况有十六种,因此解决这个问题只需枚举出这十六种情况,计算出甲乙各自的体力值,求出两者之差的绝对值。然后记录小于1000的情况,一次求出概率。
#include
#include
using namespacestd;
intmain()
{
int k[3];
int m = 1000,n = 2000,sum = 0,all = 0;
for(int i = 0; i <= 15; i ++) //枚举十六种情况
{
k[0] = (i&8) >>3; //“>>”右移符号将i与8进行&运算即保留i二进制代码的最高位,右移三位得到0,1,代码
k[1] = (i&4) >>2; //与4进行与运算保留左数第二位,右移两位得到01代码
k[2] = (i&2) >>1; //与2进行与运算保留左数第三位,右移一位得到01代码
k[3] = (i&1); //与1进行与运算直接得到01代码
for(int j = 0; j <= 3; j++)
{
if(k[j] == 0)
{
n+= m*1/4;
m =m - m*1/4;
}
else
{
m+= n*1/4;
n =n - n*1/4;
}
}
if(abs(m-n) < 1000)
{
sum++ ;
}
all++;
}
cout<<"体力值的差的绝对值小于1000的概率为"<
return 0;
}
http://blog.csdn.net/annkie/article/details/9877643
http://blog.sina.com.cn/s/blog_96b292000100yhxt.html