admin管理员组文章数量:1122852
C中getbits(x,p,n)函数、位操作详解
一、getbits(x,p,n)函数
函数getbits(x,p,n),返回x从p位置开始的(右对齐)n位的值;前提是最右边的一位为第0位。
例如:getbits(x,4,3)返回的是第2、3、4位;n此刻为3,计总共返回三位,p此刻为4,即返回位最左边为第四位。
unsigned getbits(unsigned x,int p int n)
{
return (x >> (P+1-n))&~(~0 <<n);
}
注释:设x是xxxxxxxx
~0 是11111111,左移3位,变成11111000,再取反,变成00000111
p+1-n是2,x右移2位,变成00xxxxxx
00000111
00xxxxxx
逻辑与得到红色三位,对于原x就是从第四位开始的3位.
#include <iostream>
#include <string.h>
#include <stdlib.h>
using namespace std;
unsigned getbits(unsigned x, int p, int n)
{return (x >> (p + 1 - n)) & ~(~0 << n);
}
int main() {int x = 127, x1;printf("x=%x\n", x);x1 = getbits(x, 4, 3);printf("getbits(x1)=%x\n", x1);return 0;
}
运行结果:
二、setbits(x,p,n,y)函数:
1、编写一个函数setbits(x,p,n,y),该函数返回对x执行下列的操作的结果的值:将x中从左第p位(左边第一位为0)开始的n个(二进制)位设置为y中最右边n位的值,x的其余各位保持不变
代码:
#include <stdio.h>unsigned setbits(unsigned x, unsigned p, unsigned n, unsigned y);int intLen(unsigned x);int main() {unsigned x = 171; // 1010 1011 --- > 101[0 1]011unsigned p = 3;unsigned n = 2;unsigned y = 38; // 0010 0110printf("result : %u \n", setbits(x, p, n, y));return 1;
}int intLen(unsigned x) {int len = 0;for (; x; x >>= 1) {len++;}return len;
}unsigned setbits(unsigned x, unsigned p, unsigned n, unsigned y) {int length_y = intLen(y);int length_x = intLen(x);if (length_x - p - n < 0) {printf("move over size by x");return 0;}if (length_y < n) {printf("move over size by y");return 0;}// int pos = p -n + 1;// unsigned cpy = y & ~ (~0 << n);// unsigned xx = (x >> pos) & (~0 << n);// return xx |= cpy;unsigned tail = length_x - (p + n);// x需要分离的子数据unsigned sub = x & ~(~0 << tail);// y 中需要替换的n位数据unsigned cpy = y & ~(~0 << n);// x向右移位,保留左边x >>= length_x - p;// x再向左移,这样最右边的n为可以为0x <<= n;//这样可以把y的拷贝值拷贝过去x |= cpy;// x再向左推进, 把刚刚的分离的n为先补0先x <<= tail;// x的分离再补充回数值x |= sub;return x;
}
链接:.html
2、setbits(x, p ,n, y),该函数返回对x执行下列操作后的结果值: 将x中从右第p位(最右边为0位)开始的n个(二进制)位设置为y中最右边n位的值,x的其余各位保持不变。
#include<stdio.h>unsigned setbits(unsigned x, int p, int n, unsigned y)
{return x & ~(~(~0 << n) << (p+1-n)) | (y & ~(~0 << n)) << (p+1-n);
}int main()
{unsigned int x = 73;unsigned int y = 23;int p = 5;int n = 3;int r;r = setbits(x, p, n, y);printf("%d", r); //r的结果应为121return 0;
}
三、位操作:
1、位与&
1)“位与”:& “逻辑与”:&&
2) 真值表:1&0 = 0 、0&1 = 0、0&0 = 0、1&1 = 1 只有当1与1位与时才是1,其他的值相与都是0
3)“位与”就是把2个十六进制的数先分别转换为二进制,然后再相与。“逻辑与”就是把2个十六进制分别看成2个整体,2个整体相与。
例子:0xA & 0xB = 0xA //位与 0xA && 0xB = 1 //逻辑与
0xA:1 0 1 0 0xA = 1 (ture)
0xB:1 0 1 1 0xB = 1 (ture)
位与: 1 0 1 0 逻辑与 : 1
2、位或|
1)“位或”:| “逻辑或”:||
2) 真值表:1|0 = 1 、0|1 = 1、0|0 = 0、1|1 = 1 只有两个0位或的时候才是0,其余的都是1
3) “位或”就是把2个十六进制的数先分别转换为二进制,然后再位或;“逻辑或”就是把2个十六进制分别看成2个整体,2个整体位或。
例子:0xA | 0xB = 0xB 0xA || 0xB = 1
0xA:1 0 1 0 0xA = 1 (ture)
0xB:1 0 1 1 0xB = 1 (ture)
位或: 1 0 1 1 逻辑或 : 1
3、位取反 ~
1)“位取反”:~ “逻辑取反”:!
2)“位取反”就是把十六进制数先转换为二进制,然后把每一位取反(1取反就变为0,0取反就为1);“逻辑取反”就是把十六进制数看成一个整体,然后取反(非0的数都是为真,逻辑取反后为假;0逻辑取反为真)。
3) 例子:0xA = 1 0 1 0 0xA (非0为真(即1))
~0xA = 0 1 0 1 = 0x5 !0xA = 0
~~0xA = 1 0 1 0 = 0xA !!0xA = 1
4、位异或 ^
1) “位异或”: ^
2) 真值表:1^0=1 0^1=1 0^0=0 1^1=0 两个数相等则为0,不相等则为1
3) 例子: 66 ^ 33 = 99
66: 1 0 0 0 0 1 0
33: 0 1 0 0 0 0 1
99: 1 1 0 0 0 1 1
代码: unsigned int a = 66, b = 33;
unsigned int c = a^b;
printf("c = %d ", c);
5、左移位<< 右移位>>
无符号数,左移时在右边补0,右移时在左边补0
二.位操作的实际应用
一般在操作寄存器的时候使用,如32位的arm寄存器,每个位代表的pin脚不同,效果也不同。有时候你只想改变某个pin脚的值从而实现某项功能,其余pin脚保持不变,就得使用位操作,只对目标位进行操作。操作的方式是:读->改->写。不要直接给寄存器赋目标值是因为你只知道要把目标位设置为某值,但是其他的位你并不知道原本是多少,所以要先读取这个寄存器的整体值,然后再修改其中的目标位,然后再把修改后的值写到寄存器。
1)特定位清零用&
譬如:将0xAAAAAAAA 的bit8 ~bit15清零,其他位保持不变。
分析:[位与]任何数(0/1)与1位与时为本身,与0位与为0,所以可以用位与的方式。
unsigned int a = 0xAAAAAAAA;
unsigned int b = 0xFFFF00FF;
unsigned int c;
c = a & b;
printf("c = 0x%x ", c); //c = 0xaaaa00aa
2)特定位 置1用 |
譬如:将0xffff00ff的bit8 ~bit15置1,其他位保持不变。
分析:位或 任何数(0/1)与1位或变为1,与0位或为本身
unsigned int a = 0xffff00ff;
unsigned int b = 0x000ff00;
unsigned int c;
c = a | b;
printf("c = 0x%x ", c); // = 0xffffffff
3)特定位取反用 ^
譬如:将0xffff00ff的bit8 ~bit15取反,其余保持不变
分析:位异或 任何数(0/1)与1位异或会取反,与0位异或为本身
unsigned int a = 0xffff00ff;
unsigned int b = 0xff00;
unsigned int c;
c = a ^ b;
printf("c = 0x%x ", c); // = 0xffffffff
此部分来自:
本文标签: C中getbits(xPn)函数位操作详解
版权声明:本文标题:C中getbits(x,p,n)函数、位操作详解 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/biancheng/1702795483a595704.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论