跳转至

第 15 章 位操作

第十四章 位操作

👉【复习题】【编程练习题

1. 二进制数、位和字节

以数字10为基底表示的数字称为十进制数

以数字2为基底表示的数字称为二进制数

二进制系统可以把任意整数表示为 01 的组合。

1.1 二进制整数

1字节包含8位。

C语言用字节(byte) 表示存储系统字符集所需的大小。

描述存储器芯片数据传输率中所用的字节指的是 8位 字节。

1.2 有符号整数

如何表示有符号整数取决于硬件,而不是C语言。

二进制补码方法

二进制反码方法通过反码位组合中的每一位形成一个负数。

2. 其他进制数

2.1 八进制

八进制是指八进制记数系统。

八进制数转换为二进制形式时,不能去掉中间的0

2.2 十六进制

十六进制:十六进制记数系统。

每个十六进制都对应一个4位的二进制数(即4个二进制数)。

十六进制很适合表示字节值。

3. C按位运算符

C提供按位逻辑运算符移位运算符

3.1 按位逻辑运算符

  • 二进制反码或按位取反:~

    一元运算符~把 1 变为0,把0变为1。

  • 按位与:&

    二元运算符&通过逐位比较两个运算对象,生成一个新值。

    对于每个位,只有两个运算对象中相应的位都为1时,结果才为1(从真/假方面来看,只有当两个位都为真时,结果才为真)。

    掩码:按位与运算符常用于 掩码(mask)。一些设置为 开(1)关(0)的位组合。

    关闭位(清空位):和打开特定的位类似,使用 & ,任何位与1组合都得本身(保持1号位不变,改变其他各位)。任何位与0组合都得0。

  • 按位或:|

    二元运算符 | ,通过逐位比较两个运算对象,生成一个新值。

    对于每个位,如果两个运算对象中相应的位只有一个1(非两个为1),结果为1(从真/假考虑,有一个位为真且不是为同为1,那结果为真)。

    打开位(设置位):使用按位或(|) 运算符,任何位与0组合,结果都为本身;任何位与1组合,结果都为1。

  • 按位异或^

    二元运算符

    逐位比较两个运算对象。

    对于每个位,如果一个运算对象中相应的位一个为1(但不是两个都为1),结果为1(真假来看,如果两个运算对象中相应的一个位真且不是两个同为1,结果为真)。

    切换位:打开已关闭的位,或关闭已打开的位。可以使用按位异或运算符完成。

3.2 移位运算符

  • 左移<<

    将其左侧运算对象每一位的值向左移动右侧运算对象指定的位数

    左侧运算对象移出左末端位的值丢失,用0填充空出的位置。

    (10001010)<<2 // 表达式
    (00101000) // 结果值
    
  • 右移>>

    将其左侧运算对象每一位的值向右移动其右侧运算对象指定的位数。

    左侧运算对象移出,右末端的值丢。

    对于无符号类型,用0填充空出的位置。

    对于有符号类型,其结果取决于机器。空出的位置可用0填充,或者用符号位(即最左端的位)的副本填充。

    每个位向右移动两个位置,空出的位用0填充。

总结

运算符 说明
number << n number 乘以2的n次幂
number >> n 如果number为非负,则用number除以2的次幂

4. 位字段

位字段(bit field):一个signed int 或 unsigned int 类型变量中一组相邻的位(C99和C11新增_Bool类型的位字段)

通过 结构声明来建立。此结构声明为每个字段提供标签,并确定字段的宽度。

通过普通的结构成员运算符(.)单独给字段赋值。

内含位字段的结构允许在一个存储单元中存储多个设置。

5. 对齐特性(C11)

对齐:如何安排对象在内存中的位置。

_Alignof 运算符 给出一个类型的对齐要求,在关键字 _Alignof后面的圆括号中写上类型名即可。

size_t d_align = _Alignof(float);

使用_Alignas说明符 指定一个变量类型的对齐值不应该要求该值小于基本对齐值。