c语言 字节操作,C语言位操作

C语言提供6个按位操作

<< 左移      右端补零,操作的对象是 任意 int char   这里任意是指有无符号的意思。

>> 右移      无符号数或者是正数不用考虑是左端补0, 负数看实现【一些实现补0,一些保留符号位,这种比较科学吧】

~   按位取反   【一元运算符】

&   按位与

^   按位异或

|    按位或

为了保证可移植性,寄存器当然用unsinged char 或者unsinged int ,当然更详细一点的posix标准里的

1字节     uint8_t

2字节     uint16_t

4字节     uint32_t

8字节     uint64_t

当然有符号的就是 int8_t 这样的表示。

那么

一元运算符是什么意思呢?

int i = ~k;   //操作是数只有自己啊

int i = a&b; //这样才是二元

按位很好理解就是每一位都操作一下,比如  a =0b11111001    b=0b00001110

例子:a & b

1111 1001

&     0000 1110

----------------

0000 1000

这四个符号的优先级:~    &    ^   |

避免歧义就不要吝啬括号 ,当然看了半天,想到还有 ||   &&   这个操作是逻辑操作,结果是0 或者1,和这个不太一样。

最常用的三种操作

1.设置位

2.清楚位

3.测试位

假设我们的一个8位寄存器保存在unsigned char  x 中。[0-7位]

1.比如说让一个数的第四位设置为1。 我们只需把第4位 或(|)上1 即可.

x |=  0b0001 0000

x |=  0x0100

为了更通用的写法,我们通常把第几位当成一个变量i

x |=  (1<

2.比如说让一个数的第四位清零。 我们只需把第4位 &上0 即可。

x & 0b 1110 1111

x & 0x  ef

因为构造某一位为0,我们需要给其他位填充1。我们有一种更通用的做法。

~0 便是0xfffffffffffffffff 位数就看变量的类型了,跳一步直接用i表示,我们可以得出下面的式子

x &=   ~ 0x0010

x &=  ~ (1<

3.测试第4位是否为1

if( x & 0x0010 ){  操作 }

==>

if(   x &  (1<

这里就归纳一个宏出来

#define GetBit(dat,i) ( (dat)&( 0x1<

#define SetBit(dat,i) ( (dat)|=( 0x1<

#define ClearBit(dat,i) ( (dat)&= ~( 0x01<

这里没有考虑dat是什么类型,可以C语言的关键字获取到类型后,强转一下,效果应该更好。

内核的实现

extern __inline__ int set_bit(int nr,long * addr)

{

int mask, retval;

addr += nr >> 5; //(1)

mask = 1 << (nr & 0x1f); //(2)

cli();

retval = (mask & *addr) != 0;

*addr |= mask; //(3)

sti();

return retval;

}

假设*addr = 0, nr = 3;则执行结果为1000(二进制数)

(1)如果nr大于32,则addr移动(nr/32)位数,指向下一个long 的开始位。nr>>5也就是nr除以2的5次方,等于nr/32.

(2)截取nr的低5位,然后将1左移(低5位对应的10进制数)。这样做是为了解决当nr大于31时,将1左移32位或者更多将会导致溢出(因为mask是int型,而int型在linux中是32位长)。为什么特意截取nr的低5位呢,我认为是经验,你可以试试看,比如我传递给nr的值为33,则mask的值为mask = 1 << (33 & 0x1f);   计算结果为mask=1<<1,mask=0x10,

另外说明一下:0x1f(16进制) = 11111(2进制) = 31(10进制)

对于1.2两部非常的佩服,统一了是否移位大于32位的操作

感觉指针运用的炉火纯青,关于x位处理器long的实现应该是x位吧。

通过步骤1我们知道addr指向32位的位置,那么 (*addr |= mask)就会把第33位置1了。

多位的操作

1.连续修改多位

首先用按位与清除

使用按位或存入

比如将101(0x5) 存入 4-6位

i=(i & ~0x70 )|( 0x5 >>4)

这里还需要归纳一下 0x70 因为是清理3位 那么 0x7左移动4位

i= (i & ~(0x7 >>4)  | 0x5 >>4)

那么我们只需要清理几位,放到第几位(最低位),和存入的值 即可。

#define setNbit(dat,N,low_index,value){ \

int mask=0,i=N; \

while(--i>=0){ \

mask |= (0x1<< i );\

} \

(dat) = ( (dat) & ~( mask <

}

2.连续获取多位

例:获取 3-5位

移位到最位数最右端,然后取N位

( i >>3 ) &0x7

#define getNbit(dat,N,low_index,value){\

int mask=0,i=N; \

while(--i>=0){ \

mask |= (0x1<< i ); \

}\

value = ( (dat)>>(low_index) &(mask) );\

}

感觉这种宏的实现有点蹩脚,还是用函数实现比较看起来爽一点。

void setNbit(unsigned *dat, int N, int low_index, int value)

{

int mask = 0, i = N;

while (--i >= 0)

{

mask |= (0x1 << i);

}

*dat = *dat & (~(mask << low_index)) | (value << low_index);

}

void getNbit(unsigned *dat, int N, int low_index, int *value)

{

int mask = 0, i = N;

while (--i >= 0)

{

mask |= (0x1 << i);

}

*value = (*dat >> low_index) & mask;

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值