【C++】十六进制数据的字节序排列问题、大小端

十六进制数据的字节序排列问题,涉及到 大小端(Endianness) 的概念。 包括它与大小端存储方式的关系。


1. 十六进制数据在内存中的存储

定义的数据
#define FRAME_TYPE_PARAM_SET 0x3001
  • 0x3001 是一个 16 位(2 字节)整数
  • 在内存中,0x3001 的存储方式依赖于系统的字节序:
    • 小端模式(Little Endian):低字节存储在低地址,高字节存储在高地址。
    • 大端模式(Big Endian):高字节存储在低地址,低字节存储在高地址。
两种存储方式的内存布局

0x3001 为例,16 位数值可以拆分为两个字节:

  • 高字节:0x30
  • 低字节:0x01
模式存储顺序内存布局
小端低字节 -> 高字节0x01 0x30
大端高字节 -> 低字节0x30 0x01

2. 小端与大端在数据发送中的影响

发送的数据

当你发送 0x3001 时:

  • 如果主机采用 小端模式(如 x86 处理器),数据将以小端格式排列发送:
    • 先发送低字节 0x01,再发送高字节 0x30
  • 如果主机采用 大端模式,数据将以大端格式排列发送:
    • 先发送高字节 0x30,再发送低字节 0x01
监控工具显示

监控工具通常直接按照字节顺序显示数据:

  • 如果是 小端发送
    • 数据在监控中会显示为 0x01 0x30,即你看到的 0130
  • 如果是 大端发送
    • 数据在监控中会显示为 0x30 0x01,即与定义一致。

3. 如何确认主机的字节序?

可以通过以下代码确认主机是小端还是大端:

#include <iostream>

int main() {
    uint16_t value = 0x1234;  // 定义一个16位数
    uint8_t* ptr = reinterpret_cast<uint8_t*>(&value);

    if (*ptr == 0x34) {
        std::cout << "Little Endian (小端)" << std::endl;
    } else {
        std::cout << "Big Endian (大端)" << std::endl;
    }

    return 0;
}
  • 如果输出 Little Endian,说明主机是小端模式(大多数处理器如 x86、ARM 默认是小端)。
  • 如果输出 Big Endian,说明主机是大端模式。

4. 如何解决发送时的字节序问题?

如果协议要求以 大端模式 发送数据(即高字节在前),而你的主机是 小端模式,需要在发送之前进行字节序转换。

使用系统提供的字节序转换函数

在 POSIX 系统(Linux、Windows)中,可以使用以下函数:

  • htons:将 16 位整数从主机字节序转换为网络字节序(大端)。
  • htonl:将 32 位整数从主机字节序转换为网络字节序(大端)。

示例:

#include <arpa/inet.h>  // 或 winsock2.h

uint16_t value = 0x3001;
uint16_t bigEndianValue = htons(value);  // 转换为大端
手动实现字节序转换

也可以通过位运算手动转换:

uint16_t toBigEndian(uint16_t value) {
    return (value >> 8) | (value << 8);
}

5. 总结

现象
  • 代码中定义的 0x3001 在内存中是按字节存储的。
  • 主机是小端模式时,低字节(0x01)会在前,发送时的顺序也是低字节在前,因此VS监控工具显示 0130
涉及知识点
  • 大小端模式(Endianness)
    • 小端:低字节在前(如 0x01 0x30)。
    • 大端:高字节在前(如 0x30 0x01)。
  • 网络字节序
    • 大端是网络协议的通用字节序。
    • 如果主机是小端,需要在发送前进行字节序转换。
现象
  • 如果协议要求大端格式,使用字节序转换函数(如 htons)确保发送的数据符合协议。
  • 如果协议明确允许小端格式,可以直接发送,不需要额外处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值