C语言位运算符作用,C语言中的位运算

C语言中的位运算

结构体是唯一一种允许控制内存位(bit)的数据结构,称作位域(Bit Field)

位域不能离开结构体单独存在

位域不能成为数组,但是带位域的结构体可以成为结构体数组

和位域有关的代码是取决于具体机器

用途

谨慎使用内存时(需要把几个数据放进一个字(Machine Word)

读取非标准格式(9-Bit 整型)

...

位域

struct {

unsigned int a : 1; //a占1为bit,最大为2^1 - 1 = 1

unsigned int b : 3; //b占3位bit,最大为2^3 - 1 = 7

unsigned int c : 1; //c占1位bit,最大为2^1 - 1 = 1

} exmpl;

位域是int或者unsigned int类型

一位大小的位域只能是unsigned int,因为没有符号的空间

在内存中位域被调整成int的大小(大部分机器中4 Bytes)

用例:假设有一种机器人使用1 Byte大小的数据包进行通信,但是需要发送多个状态信息

struct device {

unsigned int active : 1;

unsigned int ready : 1;

unsigned int idle : 1;

unsigned int error : 1;

} code;

d95deb071f61

内存位置

位域也可以匿名:

struct device {

unsigned int active : 1;

unsigned int ready : 1;

unsigned int idle : 1;

unsigned int error : 1;

unsigned int : 2;

unsigned int EOR : 1;

} code;

```[图片上传失败...(image-a26aed-1554036927678)]

# 位域的大小

```c

//exmpl占12 Bytes

struct {

unsigned int a : 1;

unsigned int b : 32;

unsigned int c : 1;

} exmpl;

首先给a分配内存空间,计算机将位域看作int(4 Bytes)分配空间,在第一个int中存储a后还有31位

给b分配空间时,因为第一个int剩下的31位无法存储32位的b,所以计算机开辟第二个int来储存b

第二个int已经没有多余的空间储存c,计算机单独再给c开辟一个int的空间

//exmpl占8 Bytes

struct {

unsigned int a : 1;

unsigned int b : 1;

unsigned int c : 32;

} exmpl;

首先给a分配内存空间,计算机将位域看作int(4 Bytes)分配空间,在第一个int中存储a后还有31位

然后给b分配空间,因为第一个int还剩下的31位,在第一次开辟的空间中连续存储1位的b,

第一个int已经没有多余的空间(还剩30位)储存c(32位),计算机单独再给c开辟一个int的空间

按位运算符

d95deb071f61

各种语言中的位运算符

位运算符通常被用来:测试位、设置位、移位

只有int(char)类型才可以用来位运算(一般使用char来处理bytes,int来处理words)

d95deb071f61

逻辑运算和位运算

按位NOT就是反转位(1's complement)

按位XOR就是当且仅当一个操作数为1时,按位XOR才为1

逻辑运算的结果是0或非0,但是位运算的结果是0到2^n - 1(n为一个machine word含有的位数)

位运算的用途

追踪错误

奇偶校验(Parity Check)是一种校验代码传输正确性的方法。根据被传输的一组二进制代码的数位中“1”的个数是奇数或偶数来进行校验

char get_char_from_modem(void) {

char ch;

ch = read_modem (); // 从Modem中读取一个数据

return (ch & 127);

}

d95deb071f61

奇偶校验数据

将bytes的第一位设置为校验位(标示剩下的7位中有1的数目是否位偶数)

判断校验位后,使用按位与127复制除了校验位以外的位数

2. 使用按位XOR寻找不同的位数

int x = 120;

x = 127 ^ x;

d95deb071f61

不同的位数

x为120,即差的数为7(127-120)

3. 使用求反来加密数据

d95deb071f61

数据加密

其他操作

1. 16进制表示

#include

int main(){

int n = 0x01A1;

n = n & 0xFF; /* Note: n &= 0xFF; is the same */

printf("%x\n",n); return 0;

}

//输出:a1

d95deb071f61

16进制表示

2. 使用Bit Mask检查16进制的具体位数:

//检查整数y右边的第三位是1还是0

int mask = 0x0004;

if ((y & mask) == 0)

printf("Third bit = 0\n");

else

printf("Third bit = 1\n");

d95deb071f61

Bit Mask检查

3. 使用Bit Mask修改部分位数:

//让左边的4位归零,右边的4位不动

char cmask = 0x0F;

c &= cmask;

d95deb071f61

修改部分位数

4. 移位操作:

对于左移位,全部填充的位数都是0,

对于右移位,如果标示位(第一位)是0,则全部填充0;如果标示位是1,则取决于具体实现,通常情况下填充1

数值上左移位乘2的次方倍,反之除

int n = 0x01A1;

int n1, n2, n3, n4;

n1 = n << 1; /* Value of n1 = 0x0342 */

n2 = n << 4; /* Value of n2 = 0x1A10 */

n3 = n >> 1; /* Value of n3 = 0x00D0 */

n4 = n >> 4; /* Value of n4 = 0x001A */

d95deb071f61

移位操作

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值