位运算
注:本文为学习《C语言从入门到精通》时,对部分章节的总结
1、位与字节
位是计算机存储数据的最小单位。一个二进制位可表示两种状态(0和1)。
一个字节通常由8位二进制数组成,也有由16位组成的。
2、位运算操作符
位运算符 | 含义 |
& | 按位与 |
| | 按位或 |
~ | 取反 |
^ | 按位异或 |
<< | 左移 |
>> | 右移 |
2.1、“与”运算符
a | b | a & b |
0 | 0 | 0 |
0 | 1 | 0 |
1 | 0 | 0 |
1 | `1 | 1 |
2.2、“或”运算符如果要将某几位置0,只需和这几位是0的数进行“与”操作
a | b | a | b |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 1 |
如果要将某几位置1,只需和这几位是1的数进行“或”操作
2.3、“取反”运算符
“取反”运算符“~”为单目运算符,具有右结合性。
a | ~a |
0 | 1 |
1 | 0 |
2.4、“异或”运算符
a | b | a ^ b |
0 | 0 | 0 |
0 | 1 | 1 |
1 | 0 | 1 |
1 | 1 | 0 |
经常用于一些比较简单的加密算法中。
2.5、“左移”运算符
“左移”运算符“<<”是双目运算符,功能为把“<<”左边的运算数的各二进制位全部左移若干位,由“<<”右边的数指定移动的位数,高位丢弃,低位补0。
2.6、“右移”运算符
“右移”运算符“>>”是双目运算符,功能为把“>>”左边的运算数的各二进制位全部左移若干位,由“>>”右边的数指定移动的位数。
当为正数时,高位补0,低位丢弃;为负数时,高位补0还是1由编译系统规定。移入0称为“逻辑右移”,移入1称为“算术右移”。
3、循环移位
循环左移:a、将x的左端n位先放到z中的低n位中,z = x >> (32 - n);
b、将x左移n位,其右面低n位补0,y = x << n;
c、将y与z进行按位或运算,y = y | z;
循环右移:与循环左移类似
4、位段
4.1、位段的概念与定义
位段是一种特殊的结构类型,其所有成员的长度均是以二进制为单位定义的,结构中的成员被称为位段。
结构 结构名 {
类型 变量名1:长度;
类型 变量名2:长度;
......
类型 变量名n:长度;
}
一个位段必须被说明是int、unsigned或signed中的一种。
例如,CPU的状态寄存器按位段类型定义:
struct status {
unsigned sign:1; // 符号标志
unsigned zero:1; // 零标志
unsigned carry:1; // 进位标志
unsigned parity;1; // 奇偶溢出标志·
unsigned half_carry;1; // 半进位标志
unsigned negative;1; // 减标志
} flags;
又如:
struct packed_data {
unsigned a:2;
unsigned b:1;
unsigned c:1;
unsigned d;1;
} data;
这里a、b、c、d分别占2位、1位、1位、2位
4.2、位段相关说明
a、位段类型是一种结构类型,位段类型和位段变量的定义,以及对位段(即位段类型中的成员)的引用均与结构类型和结构变量相同
b、某一位段要从另一个字节开始存放
struct status {
unsigned a:1;
unsigned b:1;
unsigned c:1;
unsigned :0;
unsigned d;1;
unsigned e;1;
unsigned f;1;
} falgs;
a、b、c存放在一个字节中,长度为0的无名位段使后面的d、e、f从下一个字节开始存储,一共占用2字节
c、一个位段必须存储在一个存储单元(通常为一字节)中,不能跨两个存储单元。如果本电源不够容纳某位段,则从下一个单元开始存储该位段
d、可以用“%d”、“%x”、“%u”和“%o”等格式字符,以整数形式输出位段
e、在数值表达式中引用位段时,系统自动将位段转换为整型数