《C Primer Plus》读书笔记】第15章:位操作

【《C Primer Plus》读书笔记】第15章:位操作

  • 15.1 二进制数、位和字节
    • 15.1.1 二进制整数
    • 15.1.2 有符号整数
    • 15.1.3 二进制浮点数
  • 15.2 其他进制数
    • 15.2.1 八进制
    • 15.2.2 十六进制
  • 15.3 C 按位运算符
    • 15.3.1 按位逻辑运算符
    • 15.3.2 用法:掩码
    • 15.3.3 用法:打开位(设置位)
    • 15.3.4 用法:关闭位(清空位)
    • 15.3.5 用法:切换位
    • 15.3.6 用法:检查位的值
    • 15.3.7 移位运算符
  • 15.4 位字段
  • 15.5 对齐特性(C11)

15.1 二进制数、位和字节

通常使用十进制来书写数字,计算机使用二进制。二进制的数字是0和1的组合,计算机通过关闭和打开的组合表示信息,这样很方便。

二进制数(binary number):以 2 为基底表示的数字。

C 语言用字节表示存储系统字符集所需的大小,所以 C 字节可能是 8 位,9 位,16 位或其他值。通常为 8 位。

15.1.1 二进制整数

C语言用字节表示存储系统字符集需要的大小,通常是8位。描述存储器芯片和数据传输率中的字节是八位字节。

15.1.2 有符号整数

二进制原码的最高位是符号位(正数为0,负数为1),后面的位是整数的绝对值的二进制表示。

正数的二进制反码和原码一样。负数的二进制反码是原码的符号位不变,其余位按位取反(1变0,0变1)。

正数的补码和原码、反码一样。负数的二进制补码是反码+1,计算机通常使用二进制补码存储整数。

二进制补码(two’s-complement):

  • 正数的高位为 0:表示正数,低七位表示数值;
  • 负数的高位为 1:表示负数,低七位各取反加一表示负值的量。

一个二进制补码的相反数,各位取反加一,因为不是对称的。

15.1.3 二进制浮点数

小数也可以用二进制表示,但是许多分数不能用二进制准确地表示。

计算机多使用IEEE 754标准存储浮点数。

15.2 其他进制数

计算机界多使用八进制和十六进制。因为8和16是2的整数次幂。

15.2.1 八进制

八进制基于8的幂,用0-7表示数字。每个八进制位对应三个二进制位。

15.2.2 十六进制

十六进制基于16的幂,用0-15表示数字,10-15分别用A-F表示(C语言中也可以用小写)。每个十六进制位对应四个二进制位。十六进制适合表示字节值。

C语言可以用位和字节进行一些操作。

15.3 C 按位运算符

C语言提供按位逻辑运算符和移位运算符。按位运算符的数据对象用一般形式表示即可。

15.3.1 按位逻辑运算符

四个按位逻辑运算符都用于整型数据(包括char)。这些操作针对每个位进行,不影响其他位。

  • ~是按位取反,把1变为0,0变为1。该运算符不改变原变量的值。

  • &是按位与,当两个相应的位都为1时才为1,否则为0。

  • |是按位或,如果两个相应的位有一个是1,结果就是1。只有都是0时结果才是0。

  • ^是按位异或,如果相应的位有一个是1,有一个是0,结果就是1。如果都为1或都为0,结果为0。

15.3.2 用法:掩码

按位与运算符常用于掩码,掩码是设置为1或0的位组合。

把一个数与一个只有一位是1,其余位是0的位进行&运算,则只有这一位不变,其余位被置为0。

flag &= MASK

可以把flag的在MASK中为1的位设置为1,相当于只有MASK为1的位才可见。

15.3.3 用法:打开位(设置位)

如果一个整数与另一个整数进行|运算,则该整数中对应另一个整数位为1的位被设置为1,其余位不变。利用这个原理可以打开位。

flag |= MASK

根据MASK中为1的位,把flag对应的位设置为1,其他位不变。

15.3.4 用法:关闭位(清空位)

如果一个整数与另一个整数进行&运算,则该整数中对应另一个整数位为0的位被设置为0,其余位不变。利用这个原理可以关闭位。

flag &= ~MASK

根据MASK中为1的位,把flag对应的位设置(清空)为0,其他位不变。

15.3.5 用法:切换位

切换一个值中的特定位的开关状态,同时保持其他位不变。

用按位异或可以切换位。

flag ^= MASK

flag中与MASK为1的位相对应的位都被切换了,MASK为0的位相对应的位不变。

15.3.6 用法:检查位的值

比较某一位的值需要覆盖其他位。

if((flag & MASK) == MASK)
	puts("Wow!");

15.3.7 移位运算符

移位运算符向左或向右移动位。

<<将左侧运算对象每一位向左移动右侧运算对象指定的位数。移出左端的位的值丢失,用0填充右端位置。左移不改变原变量的值。

>>将左侧运算对象每一位向右移动右侧运算对象指定的位数。移出右端的位的值丢失,对于无符号整数,用0填充左端位置。有符号整数的效果取决于机器,可能用0填充,也可能用符号位填充。右移不改变原变量的值。

移位运算符对2的幂进行快速有效的乘法和除法。

移位运算符可用于从较大单元中提取一些位。

15.4 位字段

位字段是一个int或unsigned int类型变量中的一组相邻的位。位字段通过一个结构声明来建立。该结构声明给每个字段提供标签,并确定该字段的宽度。

用法是在成员名后面用一个冒号,在写上所占位的数量,然后分号结束。

可以用.访问成员,赋值。但是赋值不要超过位的数量能表示的最大值。

初始化位字段结构与初始化普通结构相同。

带有位字段的结构是记录设置的方便途径。

如果总位数超过一个字节,会用下一个字节的位置,一个字段不能跨越两个字节,编译器会自动移动,从而在上一个字节留下洞。可以用未命名的字段宽度填充洞。

字段存储在int的顺序取决于机器,有的是从左向右,有的是从右向左。位字段不易移植。

15.5 对齐特性(C11)

C11的对齐特性比用位填充字节更自然,表示了C语言在处理硬件相关问题上的能力。对齐指如何安排对象在内存中的位置。

_Alignof运算符给出一个类型的对齐要求,在此关键字后的圆括号中写上类型名即可。一般对齐值是2的非负整数次幂。

可以用_Alignas说明符指定一个变量或类型的对齐值。但是不能小于基本对齐值。该说明符是声明的一部分,说明符后面的圆括号包含对齐值或类型。

你可能感兴趣的:(C,Primer,Plus,c语言,C,Primer,Plus)