C/C++中的大端和小端模式的说明、检测、转换与设置

C/C++中的大端和小端

本文在chatGPT的协助下完成,如有侵权请联系删除

在涉及到通信时(以太网/串口等)往往需要面对数据的大小端转换。
下面以图片的形式对联合体、数组、结构体等数据类型在大小端模式下在内存中的组织形式进行说明。

小端模式

  1. 定义示例 1

    typedef union InputReg_t {
        uint32_t DWord;
        uint8_t RawBytes[4];
        struct
        {
            uint32_t data : 20;
            uint32_t addr : 4;
            uint32_t cmd : 4;
            uint32_t : 4;
        };
    } InputReg_t;
    

    结果如下:
    在这里插入图片描述

  2. 定义示例 2

    typedef union InputReg_t {
        uint32_t DWord;
        uint8_t RawBytes[4];
        struct
        {
            uint32_t : 4;
            uint32_t cmd : 4;
            uint32_t addr : 4;
            uint32_t data : 20;
        };
    } InputReg_t;
    

    结果如下:
    在这里插入图片描述


大端模式

  1. 定义示例 1

    typedef union InputReg_t {
        uint32_t DWord;
        uint8_t RawBytes[4];
        struct
        {
            uint32_t data : 20;
            uint32_t addr : 4;
            uint32_t cmd : 4;
            uint32_t : 4;
        };
    } InputReg_t;
    

    结果如下:
    在这里插入图片描述

2.定义示例 2

	typedef union InputReg_t {
	    uint32_t DWord;
	    uint8_t RawBytes[4];
	    struct
	    {
	        uint32_t : 4;
	        uint32_t cmd : 4;
	        uint32_t addr : 4;
	        uint32_t data : 20;
	    };
	} InputReg_t;
结果如下:

在这里插入图片描述


大小端模式的判断

windows 平台下

  • windwos 下默认为小端模式,因此没有相关的直接判断方法

linux 平台下

  • 在头文件<endian.h>中,可以使用宏定义__BYTE_ORDER 来判断大小端,如果值为__LITTLE_ENDIAN,则为小端;如果值为__BIG_ENDIAN,则为大端

通用方法

  • __FLOAT_WORD_ORDER__:用于确定浮点数在内存中的存储顺序。

  • __BYTE_ORDER__:表示当前编译器所用的字节序。

  • __ORDER_BIG_ENDIAN__:表示采用大端字节序,即高位字节存储在低地址,低位字节存储在高地址。

  • __ORDER_LITTLE_ENDIAN__:表示采用小端字节序,即低位字节存储在低地址,高位字节存储在高地址。

  • union 结构体法:通过 union 结构体的特性,将同一内存空间的不同类型变量进行赋值,然后通过判断内存中存储的值是否与赋值时的值相同来判断大小端

  • 异或法:通过将一个整型数的地址强制类型转换为字符型指针,然后逐个取出每个字节,再通过异或运算判断大小端


大小端模式的转换

windwos

  1. 包含头文件<winsock2.h>
    • htons():将 16 位主机字节序转换成网络字节序
    • htonl():将 32 位主机字节序转换成网络字节序
    • ntohs():将 16 位网络字节序转换成主机字节序
    • ntohl():将 32 位网络字节序转换成主机字节序

linux

  1. 包含头文件<netinet/in.h>
    • htons():将 16 位主机字节序转换成网络字节序
    • htonl():将 32 位主机字节序转换成网络字节序
    • ntohs():将 16 位网络字节序转换成主机字节序
    • ntohl():将 32 位网络字节序转换成主机字节序
  2. 包含头文件<byteswap.h>
    • bswap_16():将一个 16 位整数从大端字节序转换为小端字节序或从小端字节序转换为大端字节序。
    • bswap_32():将一个 32 位整数从大端字节序转换为小端字节序或从小端字节序转换为大端字节序。
    • bswap_64():将一个 64 位整数从大端字节序转换为小端字节序或从小端字节序转换为大端字节序。
  3. 包含头文件<endian.h>
    太多了不进行详细说明

通用方法

  1. 包含头文件<stdlib.h>

    • _byteswap_ulong(): 将一个 16 位无符号整数字节序反转
    • _byteswap_ushort() : 将一个 32 位无符号整数字节序反转
    • _byteswap_uint64() : 将一个 64 位无符号整数字节序反转
  2. 编译器内置宏定义

    • __builtin_bswap16(): 将一个 16 位无符号整数字节序反转
    • __builtin_bswap32() : 将一个 32 位无符号整数字节序反转
    • __builtin_bswap64() : 将一个 64 位无符号整数字节序反转
  3. 可以使用 C11 标准库中的 freadfwrite 函数,将浮点数转换成字节流进行传输。

  4. 使用联合体来进行字节序的转换

    union {
        float f;
        uint32_t i;
    } u;
    
    u.f = 3.14;
    u.i = htonl(u.i);
    

大小端模式的设置

windows

在 Windows 上使用 GCC 和链接器改变大小端模式需要使用特定的命令行选项。以下是一些可能有用的选项:

  1. -mlittle-endian:这个选项告诉 GCC 和链接器使用小端模式。

  2. -mbig-endian:这个选项告诉 GCC 和链接器使用大端模式。

  3. -mno-ms-bitfields:这个选项告诉 GCC 不使用 Microsoft 的位域布局。

  4. -EL:这个选项告诉链接器使用小端模式。

  5. -EB:这个选项告诉链接器使用大端模式。

  6. -Wl,-EL:这个选项告诉 GCC 将 -EL 选项传递给链接器。

  7. -Wl,-EB:这个选项告诉 GCC 将 -EB 选项传递给链接器。

linux

在 Linux 下,可以使用以下命令来改变大小端模式:

  1. 通过 LDFLAGS 修改链接器标志:

    LDFLAGS=-EL
    export LDFLAGS
    
  2. 通过 CFLAGS 修改编译器标志:

    CFLAGS=-EL
    export CFLAGS
    

    其中,-EL 表示使用小端模式,-EB 表示使用大端模式。

需要注意的是,修改大小端模式可能会影响程序的二进制兼容性,因此在修改后需要进行充分的测试和验证。

  • 29
    点赞
  • 50
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值