第十五章:位操作
这一章的篇幅不是很长,但既然能单独作为一章来讲的话,应该蛮重要的,但是我貌似没有总结出多少需要注意、加强记忆的东西,可见在JAVA的日常开发过程中基本不太遇见有关位操作的内容,所以我也就不晓得那块属于本章的重点内容了。不过,不要紧,先挑我感觉比较重要的内容去记录一下。
首先,关于二进制与十进制,说大一点,还有八进制和十六进制,在之前都已经介绍过了,理解一下计算机只可以识别0、1就可以对这一些有关进制的内容有较好的理解。通常,一字节包含八位,C语言用字节来表示存储系统字符集所需的大小。可以从左到右给这八位分别编号为7~0。
C按位运算符
按位逻辑运算符,用于整型数据,包括char,这些操作都是针对每一个位进行,不影响左右两侧的位。
二进制反码或按位取反:~
一元运算符~把1变为0,把0变为1。该运算符不会改变原有的值,是创建了一个可以使用或赋值的值。
unsigned char val = 2;
~val;//2的二进制表示为00000010,那么~val的值为11111101,也就是253
unsigned char newval = ~val;
按位与:&
二元运算符,逐位比较两个运算对象,生成一个新值,对于每个位,只有两个运算对象中相应的位都为1时,结果才为1,。还有一个按位与和赋值结合的运算符: &=。
按位或:|
二元运算符,逐位比较两个运算对象,生成一个新值,对于每个位,只有两个运算对象中相应的位为1时,也就是两个位中有一个为1,结果就为1,。还有一个按位或和赋值结合的运算符: |=。
按位异或:^
二元运算符,逐位比较两个运算对象,生成一个新值,对于每个位,如果两个运算对象中相应的位为1(但不是两个为1),结果为1(也就是一真一假)。还有一个按位异或和赋值结合的运算符: ^=。
常用用法
掩码:按位与运算常用于掩码,掩码中的1表示透明,0表示不透明。使用掩码之后,会将不透明的位掩掉,因为按位与操作只要有0,结果就为0。也就是只显示需要的位数据。
打开位(设置位):打开一个值中的特定位,同时保持其他位不变。使用按位或运算符,将想要设置为1的位的码内容设置为1,想要保持不变的位码内容设置为0。
关闭位(清空位):不影响其他位的情况下关闭指定的位。使用按位与运算符,将想要设置为0的位的码内容设置为0,想要保持不变的位码内容设置为1。
切换位:打开已关闭的位,或关闭已打开的位。可以使用按位异或运算符切换位。将想要设置为开的位,对应码以及原码设置为1和0。
检查位的值:检查某位的值,要先覆盖其他位,以免产生影响。
if((flags & MASK) == MASK)//按位运算符的优先级比==低
puts(“Wow!!”);
移位运算符
左移(<< ):左移运算符将其左侧的运算对象每一位的值向左移动其右侧的运算对象指定的位数。左侧运算对象移出左末端的值丢失,用0填充空出的位置。产生一个新的值,但是并不改变运算对象。所以与赋值运算符结合可以得到(<<=)
(10001010)<<2//得到结果(00101000)
右移(>> ):右移运算符将其左侧的运算对象每一位的值向右移动其右侧的运算对象指定的位数。左侧运算对象移出右末端的值丢失,对于无符号的类型,用0填充空出的位置;有符号类型的话,取决于机器,可用0填充,或者用符号位(最左侧位)的副本填充。产生一个新的值,但是并不改变运算对象。所以与赋值运算符结合可以得到(<<=)
(10001010)>>2//得到结果(00100010)某些系统上是(11100010)
用法:针对2的幂提供快速有效的乘法和除法。
number>>n;//如果number为非负值,则number除以2的n次幂
number<<n;//number乘以2的n次幂
位字段
操纵位的第二种方法是位字段。位字段是一个signed int或unsigned int或_Bool类型变量中的一组相邻的位。通过一个结构声明来建立,该结构为每个字段提供标签,并确定该字段的宽度。可以通过普通的结构成员运算符(.)单独为这些字段赋值。
struct{
unsigned int autfd : 1;
unsigned int bldfc : 1;
unsigned int undkn : 2;
bool flag ; 1;
}prnt;
prnt.autfd = 0;
prnt.undkn = 3;
要确保所赋的值不超出字段可容纳的范围。可以使用未命名的字段宽度填充未命名的洞。使用一个宽度为0的未命名字段迫使下一个字段与下一个整数对齐。
对齐特性
_Alignof运算符给出一个类型的对齐要求,比如:
size d_align = _Alignof(float);
float类型的对齐值要求是d_align的值。可以使用_Alignas说明符指定一个变量或类型的对齐值。但是不应该要求该值小于基本对齐值。