鲜为人知的大小端问题
1. 大小端引起的问题
- 在进行
通信数据拆包解析
,不同单片机数据存储
时,因为大小端问题,产生过几个问题BUG,问题简单描述如下代码:
// 数据包的4个byte表示一个数据,如下data[4]这4个byte表示数据0x1ec99
char data[4] = { 0x00, 0x01, 0xec, 0x99 };
int value = 0;
// 直接将data[4]数据地址复制到value地址上
memcpy(&value, data, 4);
// 得到的结果为 : 0x99ec0100
printf("value = 0x%x \r\n", value);
- 问题分析如下:
(1) 对于数组
来说:
地址 | data[0] | data[1] | data[2] | data[3] |
---|---|---|---|---|
值 | 0x00 | 0x01 | 0xec | 0x99 |
(2) 将数组地址上数据 copy 到 value 地址上示意如下,但是从地址上取出数据时默认byte 4为高字节数,byte 1为低字节数
,所以取出数据:0x99ec0100
地址 | byte1 | byte2 | byte3 | byte4 |
---|---|---|---|---|
值 | 0x00 | 0x01 | 0xec | 0x99 |
(3) 通过以上分析说明,假如值 0x12345678
,实际存储方式应该如下:
地址 | byte1 | byte2 | byte3 | byte4 |
---|---|---|---|---|
值 | 0x78 | 0x56 | 0x34 | 0x12 |
(4)通过以下代码验证上面问题,打印结果为 0x78 0x56 0x34 0x12
:
int sum = 0x12345678;
char* pt = (char*)∑
for (int i = 0; i < 4; i++) {
printf("0x%x ",*(pt + i)); // 打印结果为:0x78 0x56 0x34 0x12
}
2. 大小端模式理解
-
大端模式
- 数据的
高字节保存在内存的低地址
中,而数据的低字节保存在内存的高地址
中 - 地址由小向大增加,而数据从高位往低位放
- 和我们的阅读习惯一致
- 数据的
-
小端模式
- 数据的
高字节保存在内存的高地址
中,而数据的低字节保存在内存的低地址
中 - 高地址部分权值高,低地址部分权值低
- 数据的
-
以
0x12345678
为例,两种字节序下其存储情况如下 :
大端存储方式:低地址存放高位,如下:
地址 | byte1 | byte2 | byte3 | byte4 |
---|---|---|---|---|
值 | 0x12 | 0x34 | 0x56 | 0x78 |
小端存储方式:低地址存放低位,如下:
地址 | byte1 | byte2 | byte3 | byte4 |
---|---|---|---|---|
值 | 0x78 | 0x56 | 0x34 | 0x12 |
3. 三种大小端转换方法
- 介绍3种大小端转换方法,以大端类型
0x12345678
转换成小端类型0x78563412
为例: - 方法1 : 位移运算和位操作
// 位移运算和位操作
int NetVal = 0x12345678;
int HostVal = 0;
HostVal = ((NetVal & 0x000000ff) << 24) | ((NetVal & 0x0000ff00) << 8) \
| ((NetVal & 0xff000000) >> 24) | ((NetVal & 0x00ff0000) >> 8);
printf("NetVal = 0x%x , HostVal = 0x%x\r\n", NetVal, HostVal);
- 方法2: 指针地址操作
// 指针地址操作
int NetVal = 0x12345678;
int HostVal = 0;
char* pVal = (char*)(&HostVal);
*pVal = (NetVal >> 24) & 0xff;
*(pVal + 1) = (NetVal >> 16) & 0xff;
*(pVal + 2) = (NetVal >> 8) & 0xff;
*(pVal + 3) = (NetVal >> 0) & 0xff;
printf("NetVal = 0x%x , HostVal = 0x%x\r\n", NetVal, HostVal);
- 方法3 : 利用联合结构体
// 利用联合结构体
typedef union {
int NetValue;
char data[4];
}NetToHost;
int NetVal = 0x12345678;
int HostVal = 0;
NetToHost value1;
NetToHost value2;
value1.NetValue = NetVal;
for (int i = 0; i < 4; i++) {
value2.data[i] = value1.data[3 - i];
}
HostVal = value2.NetValue;
printf("NetVal = 0x%x , HostVal = 0x%x\r\n", NetVal, HostVal);
感谢阅读,如有错误,敬请见谅!!!