字节序解析(附C++代码示例)

目录

  • 字节序是什么意思
  • 不同字节序举例
  • 整数字节序转换C++代码示例
    • 使用位操作进行转换
    • 使用`boost::endian`库进行转换
    • 使用`Poco::ByteOrder`类进行转换
  • 其他类型字节序转换
    • 字符串

字节序是什么意思

字节序(Byte Order)是指计算机中多字节数据类型(如整型、浮点型等)在内存中存储的顺序。

常见的字节序有两种:

  1. 大端序(Big-Endian):数据的高位字节存储在内存的低地址处,低位字节存储在内存的高地址处。类比于数字的书写顺序:高位在前,低位在后。
  2. 小端序(Little-Endian):数据的低位字节存储在内存的低地址处,高位字节存储在内存的高地址处。类比于数字的书写顺序:低位在前,高位在后。

字节序的选择对于数据的解析和传输都非常重要。如果发送方和接收方的字节序不一致,就会导致数据解析错误。因此,在进行跨平台数据交互时,需要明确指定和处理字节序,以确保数据的正确传输和解析。

注:可以在代码中采取条件编译,根据字节序的不同选择不同的成员顺序,以适应不同的字节序要求。这样可以保证在不同的平台上都能正确地解析数据。

不同字节序举例

  1. 大端序:
    1. 整数值 0x12345678 在内存中存储为:0x12 0x34 0x56 0x78(由4个字节组成的16进制序列,每个字节都用两个16进制数表示)
    2. 浮点数值3.14在内存中存储为:0x40 0x48 0xf5 0xc3
  2. 小端序:
    1. 整数值 0x12345678 在内存中存储为:0x78 0x56 0x34 0x12
    2. 浮点数值 3.14 在内存中存储为:0xc3 0xf5 0x48 0x40

注:不同的处理器架构和操作系统可能采用不同的字节序。例如,x86架构的处理器通常采用小端序,而网络协议常使用大端序。因此,在进行跨平台数据交互时,需要注意字节序的转换和处理,以确保数据的正确传输和解析。

整数字节序转换C++代码示例

使用位操作进行转换

我们定义了两个函数 bigEndianToLittleEndian16 和 bigEndianToLittleEndian32,用于将大端序的 16 位整数和 32 位整数转换为小端序。通过位操作和移位运算,我们可以将字节的顺序进行转换。

#include 
#include 
#include 

// 将一个 16 位整数从大端序转换为小端序
uint16_t bigEndian2LittleEndian16(uint16_t value)
{
    return (value >> 8) | (value << 8);
}

// 将一个 32 位整数从大端序转换为小端序
uint32_t bigEndian2LittleEndian32(uint32_t value)
{
    return ((value & 0xFF000000) >> 24) | ((value & 0x00FF0000) >> 8) | ((value & 0x0000FF00) << 8) | ((value & 0x000000FF) << 24);
}


int main()
{
    uint16_t bigEndian16 = 0x1234;
    uint32_t bigEndian32 = 0x12345678;

    uint16_t littleEndian16 = bigEndian2LittleEndian16(bigEndian16);
    uint32_t littleEndian32 = bigEndian2LittleEndian32(bigEndian32);

    std::cout << "Big Endian 16: 0x" << std::hex << bigEndian16 << std::endl;
    std::cout << "Little Endian 16: 0x" << std::hex << littleEndian16 << std::endl;

    std::cout << "Big Endian 32: 0x" << std::hex << bigEndian32 << std::endl;
    std::cout << "Little Endian 32: 0x" << std::hex << littleEndian32 << std::endl;

    return 0;
}

对应的小端序转为大端序的函数为:

// 将一个 16 位整数从小端序转换为大端序
uint16_t littleEndianToBigEndian16(uint16_t value) {
    return (value >> 8) | (value << 8);
}

// 将一个 32 位整数从小端序转换为大端序
uint32_t littleEndianToBigEndian32(uint32_t value) {
    return ((value & 0xFF000000) >> 24) | ((value & 0x00FF0000) >> 8) |
           ((value & 0x0000FF00) << 8) | ((value & 0x000000FF) << 24);
}

使用boost::endian库进行转换

#include 
#include 

int main()
{
    uint16_t bigEndian16 = 0x1234;
    uint32_t bigEndian32 = 0x12345678;    

    uint16_t littleEndian16 = boost::endian::native_to_little(bigEndian16);
    uint32_t littleEndian32 = boost::endian::native_to_little(bigEndian32);

    std::cout << "Big Endian 16: 0x" << std::hex << bigEndian16 << std::endl;
    std::cout << "Little Endian 16: 0x" << std::hex << littleEndian16 << std::endl;

    std::cout << "Big Endian 32: 0x" << std::hex << bigEndian32 << std::endl;
    std::cout << "Little Endian 32: 0x" << std::hex << littleEndian32 << std::endl;

    return 0;
}

对应的小端序转为大端序的示例为:

uint16_t bigEndian16 = boost::endian::native_to_big(littleEndian16);
uint32_t bigEndian32 = boost::endian::native_to_big(littleEndian32);

使用Poco::ByteOrder类进行转换

#include 
#include 

int main()
{
    uint16_t bigEndian16 = 0x1234;
    uint32_t bigEndian32 = 0x12345678;

    uint16_t littleEndian16 = Poco::ByteOrder::flipBytes(bigEndian16);
    uint32_t littleEndian32 = Poco::ByteOrder::flipBytes(bigEndian32);

    std::cout << "Big Endian 16: 0x" << std::hex << bigEndian16 << std::endl;
    std::cout << "Little Endian 16: 0x" << std::hex << littleEndian16 << std::endl;

    std::cout << "Big Endian 32: 0x" << std::hex << bigEndian32 << std::endl;
    std::cout << "Little Endian 32: 0x" << std::hex << littleEndian32 << std::endl;

    return 0;    
}

对应的小端序转为大端序的示例为:

uint16_t bigEndian16 = Poco::ByteOrder::flipBytes(littleEndian16);
uint32_t bigEndian32 = Poco::ByteOrder::flipBytes(littleEndian32);

其他类型字节序转换

对于非整数类型(如字符串、结构体等),字节序的转换需要更加谨慎和具体情况而定。一般情况下,字符串的字节序转换需要考虑字符编码的影响。

如果你需要对字符串进行字节序转换,可以将字符串转换为字节数组,然后对字节数组进行字节序转换,最后再将字节数组转换回字符串。

字符串

#include 
#include 
#include 
#include 

// 将字符串转换为字节数组std::vector
std::vector<uint8_t> string2Bytes(const std::string& str){
    // str.begin() 返回一个迭代器,指向字符串 str 的起始位置,即第一个字符处。 str.end() 返回一个迭代器,指向字符串 str 结束位置的下一个位置,即字符串末尾之后的位置。在 C++ 中,字符串是一种容器,可以使用迭代器来遍历其中的字符。
    // 使用了迭代器来遍历字符串中的每个字符,并将每个字符转换为 uint8_t 类型后添加到 std::vector 容器中。
    std::vector<uint8_t> bytes(str.begin(), str.end());
    return bytes;
}

// 将字节数组转换为字符串
std::string bytes2String(const std::vector<uint8_t>& bytes){
    std::string str(bytes.begin(), bytes.end());
    return str;
}

// 对字节数组进行字节序转换
void flipBytes(std::vector<uint8_t>& bytes){
    std::reverse(bytes.begin(), bytes.end());    
}


int main()
{
    std::string str = "Hello, World!";
    // 将字符串转换为字节数组
    std::vector<uint8_t> bytes = string2Bytes(str);
    // 对字节数组进行字节序转换
    flipBytes(bytes);
    // 将字节数组转换为字符串
    std::string convertedStr = bytes2String(bytes);

    std::cout << "Original string: " << str << std::endl;
    std::cout << "Converted string: " << convertedStr << std::endl;

    return 0;
}

你可能感兴趣的:(c++,字节序)