鲜为人知的大小端问题
1. 大小端引起的问题
- 在进行
通信数据拆包解析 ,不同单片机数据存储 时,因为大小端问题,产生过几个问题BUG,问题简单描述如下代码:
char data[4] = { 0x00, 0x01, 0xec, 0x99 };
int value = 0;
memcpy(&value, data, 4);
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));
}
2. 大小端模式理解
大端存储方式:低地址存放高位,如下:
地址 | 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);
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);
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);
感谢阅读,如有错误,敬请见谅!!!
|