C语言位运算

C语言位运算

  • 位运算符号
  • 位运算使用
  • 延伸知识点位域(位字段)
    • 位域使用

位运算符号

符号 运算方式
& (桉位与)
| (桉位或)
^ (异或)
~ (取反)
<< (左移)
>> (右移)

位运算使用

1掩码 flags &= MASK;
例如:flags二进制为 1001 0110 MASK二进制为 0000 0010 即:
flags &= 0x02;
flags = 0000 0010 这个语句将导致flags的除位 1之外,所有位都被设为 0。
2、打开位 flags |= MASK;
例如:
flags二进制为 1001 0100 MASK二进制为 0000 0010 即:
flags |= 0x02;
flags = 1001 0110 这个语句将flags中的位1设为1,并保留其他所有位不变。
结合移位运算符 flags |= MASK << n;
例如:flags二进制为 1001 0110 MASK二进制为 0000 0001 n为4即: flags |= 0x01<<4; (高电平) flags = 1001 1110 这个语句将flags的位 3 设为1,并保留其他所有位不变。
3、关闭位 flags &= ~MASK;
例如:
flags二进制为 1001 0110 MASK二进制为 0000 0010 即:
flags &= ~0x02;
flags = 1001 0100 这个语句将flags除位1设为0以外,保留其他所有位不变。
结合移位运算符 flags &= ~(MASK << n);
例如:flags二进制为 1001 0110 MASK二进制为 0000 0001 n为3即:
flags &= ~(0x01<<3); (低电平) flags = 1001 0010 这个语句将flags的位 2 设为0,并保留其他所有位不变
4、转置位 flags ^= MASK;
例如:flags二进制为 1001 0110 MASK二进制为 0000 0010 即:
flags ^= 0x02; flags = 1001 0100 转置一个位表示如果该位打开,则关闭该位,如果该位关闭,则打开该位。
5、查看一位的值
if ((flags & MASK) == MASK)
puts ("Wow);
例如:flags二进制为 1001 0110 MASK二进制为 0000 0010 即:
if ((flags & 0x02) == 0x02)
puts ("Wow);
这个语句可判断flags位1是否为1,由于位运算符的优先级低于==,因此需要在flags & MASK的两侧加上圆括号。

延伸知识点位域(位字段)

位域主要是为了去节省空间时使用的比如一个开关量,我只需要通过一个bit位即可控制,如果是8个开关量通过这样定义也大小也只有一字节。

位域使用

1.位域定义与结构定义相仿,其形式为:
struct 位域结构名
{ 位域列表 };
其中位域列表的形式为: 类型说明符 位域名:位域长度
例如:
struct ss
{
int a:8;//使用8bit
int b:2;//使用2bit
int c:6;//使用6bit
};
那么他的大小也只有两个字节
一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。
2.位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如下
struct bs
{
unsigned char a:4;
unsigned char :0;
unsigned char b:4;
unsigned char c:4;
}
****使用位域的主要目的是压缩存储,其大致规则为:

  1. 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字
    段将紧邻前一个字段存储,直到不能容纳为止;
  2. 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字
    段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
  3. 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方
    式,Dev-C++采取压缩方式;
  4. 如果位域字段之间穿插着非位域字段,则不进行压缩;
  5. 整个结构体的总大小为最宽基本类型成员大小的整数倍。****

你可能感兴趣的:(C语言篇)