iOS中位域(位段)的简单使用

在iOS蓝牙开发中(比如智能手环),由于硬件的内存比较小,通常都是只有几百K左右的可用空间,所以硬件对于内存的使用相对严谨,通常能省的字节就会进行节省。比如下面的一个蓝牙协议:
蓝牙协议

通常情况同步手机的时间可以传输UTC时间过去,UTC也是占用4个字节。但由于手环端已经完成,所以需要对此协议进行编码:(

此蓝牙协议是以年为高位,以秒为最低位进行定义。即:第31--26位为年、第25--22为月、第21--17为月、第16--12为时、第11--6为分、第5--0为秒。我们以2018年10月25日15时0分0秒为例,进行相应的编码。按照协议进行相应的编码,通过计算器得到正确的结果如下:
正确结果

换成代码,对相应的年月进行移位计算即可得到正确的答案:

    int year = 18;
    int month = 10;
    int day = 25;
    int hour = 15;
    int min = 0;
    int sec = 0;
    int temp = 0;
    temp = year<< 26 | month << 22 | day << 17 | hour << 12 | min << 6 | sec << 0;
    NSLog(@"temp===%d",temp);
    NSData*data3 = [NSData dataWithBytes:&temp length:4];
    NSLog(@"data3===%@",data3);

看下结果:
结果

结果与计算器中的结果不对,这是因为大小端的问题,进行大小端转换即可得到正确答案:

    NSData *data4 = [NSData int2Nsdata:temp];
    NSLog(@"data4===%@",data4);

+(NSData *)int2Nsdata:(int) i{
    int j =  ntohl(i);  //高低位转换
    NSData *data = [NSData dataWithBytes: &j length: sizeof(i)];
    return data;
}

再次运行结果,得到正确结果:


大小端转换后的正确结果

OK!问题解决!当然没有了,如果只是想得到结果,移位计算即可,但是为了多学习(zhuangbi),肯定想着不用这么麻烦的方法。所以引出了本文说的位域,也有的叫位段。

位域是指信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几 个不同的区域, 并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来表示。
具体来说,位域正好适合这种一个/多个字节实现多个功能,组合成一包字节的地方。定义如下:

typedef struct bit {
    unsigned int year:6;
    unsigned int month:4;
    unsigned int day:5;
    unsigned int hour:5;
    unsigned int min:6;
    unsigned int :6;
}test;

定义一个结构体,前面用类型进行修饰,代表是什么类型,后面的:X代表占用多少位,而不是单独占用一个字节。如果其中的有几位是用来占位用的,可以用最后一个秒的,不命名,到时候系统会自动进行补0。既然掌握了基本概念以后,进行编译:
位域结果

发现这个结果完全不正确啊,大小端转换后都不正确。通过查资料(百度),终于明白了,位域进行定义,是从最低位向最高位走的,所以蓝牙协议里面的最高位是年,但上面定义的完全反过来了,所以,对上面的定义进行翻转即可:

typedef struct bit {
    unsigned int :6;
    unsigned int min:6;
    unsigned int hour:5;
    unsigned int day:5;
    unsigned int month:4;
    unsigned int year:6;
}test;

进行验证:
验证结果

好的,这次彻底正确,虽说移位也能得到正确的结果,但是感觉用位域更加的简洁,毕竟只需要一个结构体就能解决。

学习(zhuangbi)完毕,有一个问题还需要请教各位大牛,移位计算中,是有一个int的temp来接收整个移位计算的值,那么如果这个位域需要得到同一个int值,可以做到吗?

你可能感兴趣的:(iOS中位域(位段)的简单使用)