user-0 提问: 关于宏定义和位段的一个题，前几天笔试时遇到的，智商捉急！百度上没搜到

回复:
user: user-1
content: 引用 7 楼 zhao4zhong1 的回复:仅供参考#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     unsigned int r;      des = WIRTE_UINT(des ,3 ,28 ,2);    //      00000000000000000000011001101101     printf("des==0x%08X\n",des);     r = READ_UINT(des ,28 ,2);     printf("r==%d\n",r);     return 0; } //des==0x0000066D //r==3 这代码看着真蛋疼。。。

user: user-2
content: 似乎没人考虑过要将十进制表示的v转成2进制表示的v?

user: user-3
content: #define msb_cn( x,n)  (((x) >>(n)) <<(n))           //后 n bits清零，保留前 sizeof (x) -n bits #define lsb_cn( x,n)  (((x) <<(n)) >>(n))           // 前 n后 n bits清零,保留后 sizeof (x) - n bits #define msb_n(x,n)   msb_cn((x),sizeof(x)*8 -(n))   //保留前 n bits，前 sizeof (x) -n bits 清零 #define lsb_n( x,n)  lsb_cn((x),sizeof(x)*8 -(n))   //保留后 n bits, 前 sizeof (x) - n bits 清零  #define replace_mn(a,v,m,n) (msb_cn((a),(m))       \                              | ((m) > (n)? lsb_n((a),((m)-(n))):0)  \                              | (lsb_n ((v),(n))<<((m)-(n))))

user: user-3
content: #define msb_cn( x,n)  (((x) >>(n)) <<(n))           //后 n bits清零，保留前 sizeof (x) -n bits #define lsb_cn( x,n)  (((x) <<(n)) >>(n))           // 前 n后 n bits清零,保留后 sizeof (x) - n bits #define msb_n(x,n)   msb_cn((x),sizeof(x)*8 -(n))   //保留前 n bits，前 sizeof (x) -n bits 清零 #define lsb_n( x,n)  lsb_cn((x),sizeof(x)*8 -(n))   //保留后 n bits, 前 sizeof (x) - n bits 清零  #define replace_mn(a,v,m,n) (msb_cn((a),(m))       \                              | ((m) > (n)? lsb_n((a),((m)-(n))):0)  \                              | (lsb_n ((v),(n))<<((m)-(n))))

user: user-4
content: 仅供参考#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     unsigned int r;      des = WIRTE_UINT(des ,3 ,28 ,2);    //      00000000000000000000011001101101     printf("des==0x%08X\n",des);     r = READ_UINT(des ,28 ,2);     printf("r==%d\n",r);     return 0; } //des==0x0000066D //r==3

user: user-5
content: 说错了，还是用了一个加法。。。。。。。。。

user: user-5
content: 在这里我没改变那4个参数，而是把replace当成一个函数，它的返回值就是你需要的。

user: user-5
content: #define replace(a,v,m,n) (((~((~0)<<n))&v)<<m)|((~((~((~0)<<(m+n))>>m)<<m))&a)  我不用减法，全部用位运算来实现。基本思想是一样的，只是操作起来不同。

user: user-6
content: 基本思路就是先用一个&把a的对应n位清0，再用一个|把v填到对应n位里面。 以n=4为例，1<<4得到10000，再减1得到1111，这就得到了一个4位的mask。把这个mask左移m位再取反，和a与一下就把a里面从m开始的n位都清0了。v和这个mask与一下再左移m位，就把v移到了需要的位置，和a或一下就填到a的对应位里面了。

user: user-6
content: #define replace(a,v,m,n) a = (a & ~(((1<<(n))-1)<<(m))) | (((v)&((1<<(n))-1))<<(m))