请教关于位移的问题。
把一个无符号整形拆成若干个数据段。
用union可以解决,但是我想通过位移和宏的方式解决。
但是苦思之下,无良策,请各位帮忙。
我想把二进制的11写到一个无符号整形的二进制表示的第28位,长度为2,且不影响其他数据。
比如原来是11001100001,用宏WIRTE_UINT之后,就变成11001101101;
同样用READ_UINT之后,就可以从第28位读取指定长度的数据。
- C/C++ code
#include <stdio.h>#define WIRTE_UINT(des ,x ,pos ,len) //怎么实现?#define READ_UINT(src ,pos ,len) //怎么实现?int main(){ unsigned int des = 1633; //原始:11001100001 des = WIRTE_UINT(des ,3 ,28 ,2); //目标:11001101101 unsigned int read = READ_UINT(des ,28 ,2); return 0;}[解决办法]
感觉WRITE的定义还是不太清楚,比如,如果x的二进制为101,而len为2,结果应当怎样?如果x等于1结果又怎样?
[解决办法]
如果暂不考虑这些不明确的定义,大致思路是:把1左移len位,然后减1变成低len位全1的值,将这个值左移一定的位数,让全1部分对准要改写的位置,然后把它取反后与dest按位相与,就可以把dest的这些位清零,之后再把x移动一定的位数,按位或上去既可。READ所用的技巧也类似。
[解决办法]
WIRTE_UINT的思路:
- C/C++ code
mask = ((1 << (len - 1)) - 1)des &= mask << pos des |= x << pos
[解决办法]
[解决办法]
- C/C++ code
#include <stdio.h>#define WIRTE_UINT(des ,x ,pos ,len) ( \ (des) \ & \ ~( \ /* 除要修改的位为0,其余都为1 */ ( \ (1<<(len))-1 \ /* 长度为len位的1 */ ) \ <<(32-(pos)-(len)) \ /* 左移32-(pos)-(len)位 */ ) \ | \ ( \ (x) \ <<(32-(pos)-(len)) \ ) \)#define READ_UINT(src ,pos ,len) ( \ ( \ ( \ (unsigned)(src) \ ) \ >>(32-(pos)-(len)) \ /* 逻辑右移32-(pos)-(len)位 */ ) \ & \ ( \ (1<<(len))-1 \ /* 长度为len位的1 */ ) \)int main() // 1111111111222222222233{ //bit 01234567890123456789012345678901 unsigned int des = 0x661; // 00000000000000000000011001100001 des = WIRTE_UINT(des ,3 ,28 ,2); // 00000000000000000000011001101101 printf("des==0x%08X\n",des); unsigned int r = READ_UINT(des ,28 ,2); printf("r==%d\n",r); return 0;}//des==0x0000066D//r==3