请教关于位移的问题。

cobra_chen 2012-07-25 12:12:51
把一个无符号整形拆成若干个数据段。
用union可以解决,但是我想通过位移和宏的方式解决。
但是苦思之下,无良策,请各位帮忙。

我想把二进制的11写到一个无符号整形的二进制表示的第28位,长度为2,且不影响其他数据。
比如原来是11001100001,用宏WIRTE_UINT之后,就变成11001101101;
同样用READ_UINT之后,就可以从第28位读取指定长度的数据。

#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;
}

...全文
732 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
cobra_chen 2012-07-26
  • 打赏
  • 举报
回复
谢谢了。
这样看起来我也就能看懂了。

[Quote=引用 12 楼 的回复:]

嘢!终于找到在宏定义中用续行符\和/*注释*/能编译通过的方法了!
可惜CSDN带汉字的代码行字符宽度不一致导致对齐不好看。
C/C++ code
#include <stdio.h>

#define WIRTE_UINT(des ,x ,pos ,len) ( \
(des) ……
[/Quote]
赵4老师 2012-07-26
  • 打赏
  • 举报
回复
嘢!终于找到在宏定义中用续行符\和/*注释*/能编译通过的方法了!
可惜CSDN带汉字的代码行字符宽度不一致导致对齐不好看。
#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
pathuang68 2012-07-25
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]

如果暂不考虑这些不明确的定义,大致思路是:把1左移len位,然后减1变成低len位全1的值,将这个值左移一定的位数,让全1部分对准要改写的位置,然后把它取反后与dest按位相与,就可以把dest的这些位清零,之后再把x移动一定的位数,按位或上去既可。READ所用的技巧也类似。
[/Quote]

++
AnYidan 2012-07-25
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 的回复:]

可否稍微解释一下?
引用 5 楼 的回复:

C/C++ code
#include <stdio.h>

#define WIRTE_UINT(des ,x ,pos ,len) ((des)&amp;~(((1<<(len))-1)<<(32-(pos)-(len)))|((x)<<(32-(pos)-(len))))
#define READ_UINT(src ,……
[/Quote]
移位, & 或 | 位操作
cobra_chen 2012-07-25
  • 打赏
  • 举报
回复
可否稍微解释一下?
[Quote=引用 5 楼 的回复:]

C/C++ code
#include <stdio.h>

#define WIRTE_UINT(des ,x ,pos ,len) ((des)&~(((1<<(len))-1)<<(32-(pos)-(len)))|((x)<<(32-(pos)-(len))))
#define READ_UINT(src ,pos ,len) ((((unsigned)(src))……
[/Quote]
赵4老师 2012-07-25
  • 打赏
  • 举报
回复
#include <stdio.h>

#define WIRTE_UINT(des ,x ,pos ,len) ((des)&~(((1<<(len))-1)<<(32-(pos)-(len)))|((x)<<(32-(pos)-(len))))
#define READ_UINT(src ,pos ,len) ((((unsigned)(src))>>(32-(pos)-(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
图灵狗 2012-07-25
  • 打赏
  • 举报
回复
WIRTE_UINT的思路:

mask = ((1 << (len - 1)) - 1)
des &= mask << pos
des |= x << pos

READ_UINT用类型的方法即可。
夏天__ 2012-07-25
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 的回复:]

C/C++ code
#include <stdio.h>

#define WIRTE_UINT(des ,x ,pos ,len) ( \
(des) \
& \
~( ……
[/Quote]
楼上厉害。学习了。
赵4老师 2012-07-25
  • 打赏
  • 举报
回复
提醒:加了上面/* ... */注释后编译错误,需要去掉所有/* ... */注释后才能编译通过。
晨星 2012-07-25
  • 打赏
  • 举报
回复
如果暂不考虑这些不明确的定义,大致思路是:把1左移len位,然后减1变成低len位全1的值,将这个值左移一定的位数,让全1部分对准要改写的位置,然后把它取反后与dest按位相与,就可以把dest的这些位清零,之后再把x移动一定的位数,按位或上去既可。READ所用的技巧也类似。
晨星 2012-07-25
  • 打赏
  • 举报
回复
感觉WRITE的定义还是不太清楚,比如,如果x的二进制为101,而len为2,结果应当怎样?如果x等于1结果又怎样?
赵4老师 2012-07-25
  • 打赏
  • 举报
回复
#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


自从上次做了一个NUTS2000使用方法以来,得到广大NMR战友们的喜爱,由于懒惰,很久都没有写过有总结性的东西了,Mestrec版本到了4.9.9.9,已经停止了这个系列的开发,从5.0开始,现在已经改名为MestreNova了,虽然MestreNova在处理效果方面,比Mestrec上了一个档次,但是功能方面,好像还没有完善,因此到目前位置,我觉得还是有必要对Mestrec的使用方法做一下总结,毕竟现在大部分人都在用Mestrec,而且网上还没有一个像样的教程,有几个教程都没有涉及到二维的处理。因此我就花上几天的时间,在这里给大家做这个教程,呵呵。若有不对的地方,还希望大家指出来,我会虚心请教的。此教程首先发布在中国核磁共振论坛:http://www.nmrbbs.cn 本教程包括一维和二维的处理方法,图文并茂,希望大家喜欢。 本教程包括如下内容: 一、Mestrec一维处理教程 1、 运行软件 2、 打开Fid文件 3、 傅立叶变换 4、 相位矫正 5、 基线矫正 6、 图谱放大 7、 定标 8、 标注化学位移 9、 积分 10、添加注释 11、图谱叠加 12、添加放大图 13、拷贝到word文档 14、导出ascii码,以便origin画图 二、常用设置 1、 背景设置 2、 图谱设置,包括图谱、参数、横坐标、纵坐标、化学位移、积分等设置 三、Mestrec二维处理教程 1、 打开fid文件 2、 傅立叶变换 3、 二维谱边上调用一维图谱 4、 二维图谱放大 5、 其他操作和一维基本相同 湖北大学 柴仕淦 2008.4.28

69,374

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧