1. 关键词

关键词:

C++ 大端 小端 数据转换 跨平台

大小端的定义:

大端(Big Endian)和小端(Little Endian)是指在计算机内存中存储多字节数据类型的字节顺序。以下是它们的区别:

大小端定义区别示例(0x1234)
大端数据的最高有效字节(Most Significant Byte, MSB)存储在内存的最低地址,而最低有效字节(Least Significant Byte, LSB)存储在内存的最高地址。最高有效字节存储在最低地址<br/>又称:网络字节序内存地址: 高 -> 低<br/>存储内容: 0x34 0x12
小端数据的最低有效字节(Least Significant Byte, LSB)存储在内存的最低地址,而最高有效字节(Most Significant Byte, MSB)存储在内存的最高地址。最低有效字节存储在最低地址<br/>又称:主机字节序内存地址: 高 -> 低<br/>存储内容: 0x12 0x34

实现原理:

通过高低地址位的数据判断大端或小端。

应用场景:

  • 网络传输协议中,大端和小端的字节序不同,需要转换为网络字节序。
  • 不同平台的数据交换,需要转换为统一的字节序。

2. sysutil.h

#pragma once

#include <cstdint>
#include <string>

namespace cutl
{
    /**
     * @brief Endianness type.
     *
     */
    enum class endian
    {
        /** little endian */
        little,
        /** big endian */
        big,
    };

    /**
     * @brief Get the program endianness.
     *
     * @return endian the program endianness.
     */
    endian endian_type();
    /**
     * @brief Byteswap a 16-bit value.
     *
     * @param value the value to byteswap.
     * @return uint16_t the byteswapped value.
     */
    uint16_t byteswap(uint16_t value);
    /**
     * @brief Byteswap a 32-bit value.
     *
     * @param value the value to byteswap.
     * @return uint32_t the byteswapped value.
     */
    uint32_t byteswap(uint32_t value);
    /**
     * @brief Byteswap a 64-bit value.
     *
     * @param value the value to byteswap.
     * @return uint64_t the byteswapped value.
     */
    uint64_t byteswap(uint64_t value);
    /**
     * @brief Byteswap an array of bytes.
     *
     * @param data the array of bytes to byteswap.
     * @param size the size of the array.
     */
    void byteswap(uint8_t *data, uint32_t size);
} // namespace cutl
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.

3. sysutil.cpp

#include <map>
#include <iostream>
#include <strutil.h>
#include <cstdlib>
#include "sysutil.h"
#include "inner/logger.h"
#include "inner/system_util.h"
#include "inner/filesystem.h"

namespace cutl
{
    endian endian_type()
    {
        int a = 1;
        int *p = &a;
        uint8_t *pBtye = (uint8_t *)p;
        if (*pBtye == 1)
        {
            return endian::little;
        }
        else
        {
            return endian::big;
        }
    }

    uint16_t byteswap(uint16_t value)
    {
        auto data = (uint8_t *)(&value);
        byteswap(data, 2);
        return value;
    }

    uint32_t byteswap(uint32_t value)
    {
        auto data = (uint8_t *)(&value);
        byteswap(data, 4);
        return value;
    }

    uint64_t byteswap(uint64_t value)
    {
        auto data = (uint8_t *)(&value);
        byteswap(data, 8);
        return value;
    }

    void byteswap(uint8_t *data, uint32_t size)
    {
        uint32_t n = size / 2;
        for (uint32_t i = 0; i < n; i++)
        {
            uint8_t temp = data[i];
            data[i] = data[size - i - 1];
            data[size - i - 1] = temp;
        }
    }
} // namespace cutl
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.
  • 55.
  • 56.
  • 57.
  • 58.
  • 59.

4. 测试代码

#include "common.hpp"
#include "sysutil.h"

void TestEndian()
{
    PrintSubTitle("TestEndian");

    if (cutl::endian_type() == cutl::endian::little)
    {
        std::cout << "OS endianness: little endian" << std::endl;
    }
    else
    {
        std::cout << "OS endianness: big endian" << std::endl;
    }

    uint16_t a = 0x1234;
    std::cout << "byteswap for a: " << cutl::to_hex(cutl::byteswap(a)) << std::endl;
    uint32_t b = 0x12345678;
    std::cout << "byteswap for b: " << cutl::to_hex(cutl::byteswap(b)) << std::endl;
    uint64_t c = 0x123456789ABCDEF0;
    std::cout << "byteswap for c: " << cutl::to_hex(cutl::byteswap(c)) << std::endl;
    uint8_t bytes[] = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10};
    cutl::byteswap(bytes, 16);
    std::cout << "byteswap for bytes: " << cutl::to_hex(bytes, 16) << std::endl;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.

5. 运行结果

---------------------------------------------TestEndian---------------------------------------------
OS endianness: little endian
byteswapfor a: 3412
byteswap for b: 78563412
byteswap for c: F0DEBC9A78563412
byteswap for bytes: 10 0F 0E 0D 0C 0B 0A 09 08 07 06 05 04 03 02 01 
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.

6. 源码地址

更多详细代码,请查看本人写的C++ 通用工具库:  common_util, 本项目已开源,代码简洁,且有详细的文档和Demo。

本文由博客一文多发平台  OpenWrite 发布!