深入分析根据字节取数据
来源:互联网 发布:淘宝发布宝贝草稿箱 编辑:程序博客网 时间:2024/06/03 17:26
如何将一个数据包中的部分数据提取出来,并转化为有效数据,相信这是很多做网络、串口的同仁们遇到的问题,希望这篇文章能给你一些思路:)
如果我们想要提取特定字节数的数据,首先大家可能想到的是按位提取,通过移位操作的方法,我本科时候也是这么做的,但是这里有缺点:非常难懂,不容易修改。过了几天自己都不知道怎么编写的了,这里使用另外一种办法,巧妙地利用基本类型来取出数据。
一、利用typedef统一规范
废话少说,先统一规范:
typedef unsigned char u8;typedef unsigned short u16;typedef unsigned long u32;
我们通过sizeof进行查看,发现无论在32位还是64位的编译器环境下:
u8=1(字节) u16=2(字节) u32=4 (字节)
这就非常巧妙了,无论什么环境,我们提前定义好的u8,u16,u32就像一个漏斗。程序员给u8说,我给你一个地址,你以这个地址起始取出1个字节的数据来,u8只能乖乖地去内存那里取出8位数据来。想取多(非法访问)也没有办法吖,尺寸所限!说到这里,你大概明白我想干什么了吧~
二、从一个简单的例子讲起
这里在一个C++的文件编写C程序,为什么要用C++呢,因为在C++兼容的C规范更加严格,不允许一些模糊的类型变换,此刻我们开始使用u8这个漏斗啦
u32 x = 0x11223344; u8 *c =(u8 *)&x; printf("x1=%x\n",*(c)); printf("x2=%x\n",*(c+1));
这里以一个最简单的例子作为说明,假设我们定义一个4个字节的数据(当然你也可以理解为在内存中存储连续4个字节的数据),由于我们在X86架构下为小端模式,所以我们剧透下:低地址起始的一个字节为0x44,我们要做的就是取出这个数据来~
首先,我们需要定义一个指针,这个指针指向的地址为变量x的地址,能够访问的长度为1个字节,如下:
u8 *c =&x; //错误,C++下不通过,地址类型不匹配u8 *c =(u8 *)&x; //正确
需要注意的是,虽然我们的想法是正确的,但是编译器是不会通过的,因为变量x是一个4字节的数据,我们使用一个u8的指针访问4字节变量的地址,左右类型不匹配,因此我们需要使用(u8 *)&x进行强制转换。得到的结果就是0x44。
如何直接访问呢?
printf("x1=%x\n",*(u8*)(&x));
1,取变量x的地址: (&x)
2,1个字节对应的指针:(u8*)(&x)
3,由于()的优先级比解引用”*”高:*(u8*)(&x))
三、提升难度版
如果我们想随心所欲的提取数据,该怎么办?这里同样以变量x为例,提取出变量x的低4个字节和高4个字节。
//使用中间变量,简单 u16 *d =(u16 *)&x; printf("x1=%x\n",*(d)); printf("x2=%x\n",*(d+1));//直接访问,复杂 printf("x1=%x\n",*(u16*)(&x)); printf("x2=%x\n",*((u16*)(&x)+1));
这里分析直接访问的代码,仍然按照刚才的办法进行分解:
1,取变量x的地址: (&x)
2,2个字节对应的指针:(u16*)(&x)
3,由于()的优先级比解引用”*”高:*(u16*)(&x))
4,如果继续提取,首先对地址+1,然后解引用:*( (u16*)(&x) +1 )
四、代码验证
#include <stdio.h>#include <stdlib.h>typedef unsigned char u8;typedef unsigned short u16;typedef unsigned long u32;int main(){ printf("u8=%d,u16=%d,u32=%d\r\n",sizeof(u8),sizeof(u16),sizeof(u32)); u32 x = 0x11223344; printf("---------取一个字节-----------\r\n"); u8 *c =(u8 *)&x; printf("x1=%x\n",*(c)); printf("x2=%x\n",*(c+1)); printf("x3=%x\n",*(c+2)); printf("x4=%x\n",*(c+3)); printf("x1=%x\n",*(u8*)(&x)); printf("x2=%x\n",*((u8*)&(x)+1)); printf("x3=%x\n",*((u8*)&(x)+2)); printf("x4=%x\n",*((u8*)&(x)+3)); printf("---------取两个字节-----------\r\n"); u16 *d =(u16 *)&x; printf("x1=%x\n",*(d)); printf("x2=%x\n",*(d+1)); printf("x1=%x\n",*(u16*)(&x)); printf("x2=%x\n",*((u16*)(&x)+1)); printf("---------取四个字节-----------\r\n"); //u32 *p =(u32*)&x; u32 *p =&x; printf("x1=%x\n",*(p)); printf("x1=%x\n",*(&x)); system("pause"); return 0;}
截图:
u8=1,u16=2,u32=4
———取一个字节———–
x1=44
x2=33
x3=22
x4=11
x1=44
x2=33
x3=22
x4=11
———取两个字节———–
x1=3344
x2=1122
x1=3344
x2=1122
———取四个字节———–
x1=11223344
x1=11223344
- 深入分析根据字节取数据
- JAVA 根据时间段取数据
- 从长整型数据取字节
- 根据分类分别取数据算法
- mybatis根据id循环取数据
- 根据用户ID爬取Twitter数据
- MySql函数之根据时间取数据
- JMP数据深入分析
- 数据包头分析---网络字节序与主机字节序
- ARM程序由于字节对齐引起的问题深入分析
- ARM程序由于字节对齐引起的问题深入分析
- ARM程序由于字节对齐引起的问题深入分析
- 带你分析字节码-深入理解class(一)
- 带你分析字节码-深入理解class(二)
- 通过字节码深入分析java的枚举类型enum
- 天猫数据爬取分析
- 数据分析FineReport优化报表取数
- java中return与finally的执行顺序分析(根据字节码分析)
- Qt多界面及相互import
- Windows7 64位+python3.4环境下安装opencv3.0的方法
- async和await
- sql server
- Python015面向对象之类和对象
- 深入分析根据字节取数据
- java刷题笔记-线程
- 花
- 【PAT】【Advanced Level】1123. Is It a Complete AVL Tree (30)
- GetModuleHandle
- UnicodeEncodeError: 'gbk' codec can't encode character: illegal multibyte sequence
- python设置编码格式utf-8
- 自己编写的两级队列的线程池(根据ThreadPoolExecuuor)
- 前端性能优化漫谈----用户