一个关于位运算的宏定义求解(百分悬赏)!!

liyachen777 2014-07-24 04:48:10
我们大一学生在做课程设计,我在网上找的一个程序中的一个宏定义在答辩时被老师提问道,我不会······求各位大神解答!!!
#define MCGETLONG(data) ( ( ((unsigned long)MCGETSHORT((data)))<<16 )|( ((unsigned long)MCGETSHORT((char *)(data)+2))&0x0000ffff ) )
老师还举了个例子
a=1b2ec
b=MCGETLONG(a)
问b得多少
大家给解答下,还有原理是什么,能不能提前回家全看大家了,谢谢啦!!!!!!!!!!
...全文
690 33 打赏 收藏 转发到动态 举报
写回复
用AI写文章
33 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2015-07-15
  • 打赏
  • 举报
回复
dlut_ppp 2015-07-15
  • 打赏
  • 举报
回复
。。这个运算怎么逆过来啊。楼主做了吗
caxa1126 2014-07-25
  • 打赏
  • 举报
回复
顶,只为赚分
mymtom 2014-07-25
  • 打赏
  • 举报
回复
GETLONG就是从data指向的地址取4个字节,组成一个32位的unsigned long

#define MCGETCHAR(data)  (*((char *)(data)))
#define MCGETSHORT(data) \
        ((unsigned short)(( ((unsigned short)(*((char *)(data))))<<8 )|( ((unsigned short)(*((char *)(data)+1)))&0x00ff )))
#define MCGETLONG(data) \
        ( ( ((unsigned long)MCGETSHORT((data)))<<16 )|( ((unsigned long)MCGETSHORT((char *)(data)+2))&0x0000ffff ) )
#define MCGET3BN(data)  \
        ( ( ((unsigned long)MCGETCHAR((data)))<<16 )|( ((unsigned long)MCGETSHORT((char *)(data)+1))&0x0000ffff ) )

#include <stdio.h>

int
main(int argc, char *argv[])
{
        char buf[4] = {0x12, 0x34, 0x56, 0x78};
        unsigned char  uc;
        unsigned short us;
        unsigned long  ul; 
        unsigned long  u3;

        /* 取一个字节 */
        uc = MCGETCHAR(buf);
        /* 取两个字节,组成short */
        us = MCGETSHORT(buf);
        /* 取四个字节,组成long */
        ul = MCGETLONG(buf);
        /* 取3个字节, 作为long的低24位, 高8位是零 */
        u3 = MCGET3BN(buf);

        printf("0x%02x 0x%04x 0x%08x 0x%08x\n", uc, us, ul, u3);

        return 0;
}

/* 输出:
 0x12 0x1234 0x12345678 0x00123456
 */
caewow 2014-07-25
  • 打赏
  • 举报
回复
就是将高地址和低地址上的值互换
formal1123 2014-07-25
  • 打赏
  • 举报
回复
看着有中想跪的感觉
707wk 2014-07-25
  • 打赏
  • 举报
回复
liyachen777 2014-07-24
  • 打赏
  • 举报
回复
引用 24 楼 Idle_ 的回复:
不就是大小端互换吗?
知道啦,谢啦谢啦~~~
liyachen777 2014-07-24
  • 打赏
  • 举报
回复
引用 23 楼 zilaishuichina 的回复:
[quote=引用 21 楼 zilaishuichina 的回复:] 应该是 第2字节在最高位 第1字节在次高位 第4字节在次低位 第3字节在最低位
错了 还是 低地址的数据在高位,高地址的数据在低位 比如 int a = 0x12345678 int b=MCGETLONG(&a) //b = 0x78563412[/quote]搜噶····
阿呆_ 2014-07-24
  • 打赏
  • 举报
回复
不就是大小端互换吗?
zilaishuichina 2014-07-24
  • 打赏
  • 举报
回复
引用 21 楼 zilaishuichina 的回复:
应该是 第2字节在最高位 第1字节在次高位 第4字节在次低位 第3字节在最低位
错了 还是 低地址的数据在高位,高地址的数据在低位 比如 int a = 0x12345678 int b=MCGETLONG(&a) //b = 0x78563412
边走边瞧 2014-07-24
  • 打赏
  • 举报
回复
zilaishuichina 2014-07-24
  • 打赏
  • 举报
回复
应该是 第2字节在最高位 第1字节在次高位 第4字节在次低位 第3字节在最低位
zilaishuichina 2014-07-24
  • 打赏
  • 举报
回复

#define MCGETSHORT(data)													\
(																			\
	(unsigned short)(														\
						(													\
							(												\
								(unsigned short)(							\
													*(						\
														(char *)(data)		\
													)						\
												)							\
							) << 8											\
						)													\
																			\
						|													\
																			\
						(													\
							(												\
								(unsigned short)(							\
													*(						\
														(char *)(data) +1	\
													)						\
												)							\
							) & 0x00ff										\
						)													\
					)														\
)

//data值所代表的那个地址,比如data为0x1b2ec,
//(char *)(data)就是内存地址0x1b2ec
//*((char *)(data))就是内存地址0x1b2ec里面的值X
//(unsigned short)(*((char *)(data)))从地址0x1b2ec取一个char数据然后强转为short数据Y1
//Y1右移八位,就是比如Y1是0x12,变成0x1200

//下面类似
//(char *)(data) + 1 就是内存地址0x1b2ed
//(unsigned short)(*((char *)(data)))从地址0x1b2ed取一个char数据然后强转为short数据Y2
//Y2 & 0x00ff,就是比如Y2是0x34,变成0x0034

//Y1 | Y2 就是 0x1200 | 0x0034 = 0x1234

//(unsigned short)(Y1 | Y2) 强转为short

//MCGETLONG类似
a=1b2ec // 这个应该是0x1b2ec b=MCGETLONG(a) 取得地址为0x1b2ec里面4个字节的数据 低地址的数据在高位,高地址的数据在低位
勤奋的小游侠 2014-07-24
  • 打赏
  • 举报
回复
引用 14 楼 liyachen777 的回复:
[quote=引用 11 楼 lovesmiles 的回复:] 你写漏东西了 //声明宏函数
#define MCGETCHAR(data)  (*((char *)(data)))
#define MCGETSHORT(data)  ((unsigned short)(( ((unsigned short)(*((char *)(data))))<<8 )|( ((unsigned short)(*((char *)(data)+1)))&0x00ff ))) //这是对short的处理,就是两个字节,将低字节复制到高位
#define MCGETLONG(data)  ( ( ((unsigned long)MCGETSHORT((data)))<<16 )|( ((unsigned long)MCGETSHORT((char *)(data)+2))&0x0000ffff ) )
//这是对long的处理,就是四个字节,将低两字节复制到高位两字节 MCGETLONG展开后的结果就是四个字节的值都用低位字节的值表示。。
··········额,那如果给了一个超出四位的数呢·····[/quote] unsgined long的长度就是4个字节,怎么超?超过了就当它只有4个字节,高位的全部看不见。
勤奋的小游侠 2014-07-24
  • 打赏
  • 举报
回复
引用 16 楼 liyachen777 的回复:
引用 5 楼 zilaishuichina 的回复:
求 MCGETSHORT
下面有,求解啊,大神!
给个直观的例子你: 例如 data = 0xabcd; data1 = MCGETLONG(data); data1 就是0xdddd 就是将最低位的d复制到这四字节。
baichi4141 2014-07-24
  • 打赏
  • 举报
回复
引用 12 楼 liyachen777 的回复:
大神,那要是出个十六进制数,是不是先转成二进制,然后右移16位,然后跟后面那个比较???额···还是晕了,能通俗一点么····
内存中的所有数据都是2进制,如果人要看的话可以转换成十六进制给人看 右移十六位是数学运算,即乘以2的16次方,和内存大小端没有关系 要容易理解,你可以把这个宏写成函数,每一个小运算都单独列一行,然后理解起来就容易得多,也可以一边调试一边观察 像这种有点复杂的运算,其实建议写成内联函数,比写成宏好得多
liyachen777 2014-07-24
  • 打赏
  • 举报
回复
引用 5 楼 zilaishuichina 的回复:
求 MCGETSHORT
下面有,求解啊,大神!
liyachen777 2014-07-24
  • 打赏
  • 举报
回复
引用 13 楼 lovesmiles 的回复:
抄个代码也不会看啊,我把你的源码在网上找到了
int read(char acFilePath[])
{
 int nsizecount = 2 ;     //结构体数组从第二个位置开始存储数据 ;
 FILE* pfp ;              //指针指向二进制文件 ;
 
 char actotalsize[2] ;    //从二进制文件中读取道路信息的总体数据长度 ;
 char aclinkId[4] ;       //从二进制文件中读取道路编号 ;
 char acroadnamesize[2] ; //从二进制文件中读取道路名称数据长度;
 char acNodeInfo[4] ;     //存储从二进制文件中读取的值 ;
 pfp = FileOpen( acFilePath ) ;
                          //读取文件: 打开原始文件或用户手动输入的文件路径名称 ;

 start=clock();
 printf("\n\t   读取文件.") ;
    printf("\n\t   读取中......") ;
  
    while( 1 )                 //循环读取数据,直到pfp指针指向文件的末尾 ;
 {
      if( fread( actotalsize , sizeof(actotalsize) , 1 , pfp ) == NULL )
  { 
      fclose(pfp) ;
      end=clock();
      printf("\n\t   文件读取成功,用时%f秒\n\n",(double)(end-start)/CLOCKS_PER_SEC);
      return nsizecount-1 ;
  }
 
     fread( aclinkId , sizeof(aclinkId) , 1 , pfp ) ;         //读取占用4字节的linkId字符串;
     fread( acroadnamesize , sizeof(acroadnamesize) , 1 , pfp ) ;
                             //读取占用2字节的roadnamesize字符串;
     fread( acNodeInfo , sizeof(acNodeInfo) , 1 , pfp ) ;       
                            //读取占用4 字节的dispclass , brunch , 和 roadnameflag字符串 ;
                            //调用宏函数 , 将字符串信息转化为数值类型  ;
        unsigned short ustotalsize = MCGETSHORT( actotalsize ) ;
        unsigned long  ullinkId = MCGETLONG( aclinkId ) ;
        unsigned short usroadnamesize = MCGETSHORT( acroadnamesize ) ;
 
                            //赋值 :将数值信息传到结构体中  ;
        road[nsizecount].ussize = ustotalsize ;
        road[nsizecount].ullinkId = ullinkId ;
        road[nsizecount].usroadnamesize= usroadnamesize ;
 
                           //从一个字节中读取dispclass , brunch 以及roadnameflag的值 ;
     int m=(int)acNodeInfo[3]&255;
     road[nsizecount].usdispclass=m&15;
     road[nsizecount].usbrunch=(m&112)/16;
     road[nsizecount].usroadnameflag=(m&128)/128;
                          //从文件中读取道路名称 ;
     fread( &road[nsizecount].roadname , sizeof(char) , ustotalsize - 12 , pfp ) ;
     
     nsizecount++;
 }   
  return 0;
}
额······那我的四句宏定义是不是就是这个功能·····
liyachen777 2014-07-24
  • 打赏
  • 举报
回复
引用 11 楼 lovesmiles 的回复:
你写漏东西了 //声明宏函数
#define MCGETCHAR(data)  (*((char *)(data)))
#define MCGETSHORT(data)  ((unsigned short)(( ((unsigned short)(*((char *)(data))))<<8 )|( ((unsigned short)(*((char *)(data)+1)))&0x00ff ))) //这是对short的处理,就是两个字节,将低字节复制到高位
#define MCGETLONG(data)  ( ( ((unsigned long)MCGETSHORT((data)))<<16 )|( ((unsigned long)MCGETSHORT((char *)(data)+2))&0x0000ffff ) )
//这是对long的处理,就是四个字节,将低两字节复制到高位两字节 MCGETLONG展开后的结果就是四个字节的值都用低位字节的值表示。。
··········额,那如果给了一个超出四位的数呢·····
加载更多回复(13)

69,369

社区成员

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

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