跳转至

第二十章 低级程序设计

前面几章中讨论的是C语言中高级的、与机器无关的特性。有一些程序需要进行位级别的操作。位操作和其他一些低级运算在编写系统程序、加密程序、图形程序以及一些需要高执行速度或高效地使用空间的程序时非常有用。

本章描述的一些技术需要用到数据在内存中如何存储的知识,这对不同机器和编译器可能会不同。依赖于这些技术很可能会使程序丧失可移植性。


按位运算符

移位运算符

移位运算符可以改变数的二进制形式,将它的位向左或者向右移动。

符号 含义
<< 左移位
>> 右移位

运算符<<>>的操作数可以是任意整数型或字符型的。对两个操作数都会进行整数提升,返回值的类型是左边操作数提升后的类型。

i<<j的值是将i中的位左移j位后的结果。每次从i的最左端溢出一位,在i的最右端补一个0位。i>>j的值是将i中的位右移j位后的结果。如果i是无符号数或非负数,则需要在i的最左端补0。如果i是负值,其结果是由实现定义的。一些补0,一些补1。

Note

可移植性技巧:最好仅对无符号数进行移位运算。

按位求反、按位与运算符、按位异或运算符和按位或运算符

符号 含义
~ 按位求反
& 按位与
^ 按位异或
| 按位或

上面的顺序也是运算符优先级的顺序。

结构中的位域

C语言提供了声明成员为位域的结构。

比如:

struct file_date {
    unsigned int day:5;
    unsigned int month:4;
    unsigned int year:7;
};

struct file_data fd;
fd.day = 28;
fd.month = 12;
fd.year = 8; /* represents 1988 */

这个结构占据32个比特,每个成员后面的数字指定了它所占用位的长度。

位域有一个限制,C语言不允许将&运算符作用于位域。

位域之间没有间隙,直到剩下的空间不够用来放下一个位域了,这时,一些编译器会跳到下一个存储单元继续存放位域,而另一些则会将位域拆开跨存储单元存放。位域的存放的顺序也是由实现定义的。