更改联合内的字节顺序或字节顺序

Changing endianness or byte order within a union

我正在从事一个涉及通信的项目。我希望能够获取一个结构并将其转换为字节以准备传输。不幸的是,字节顺序不适合我。

我正在使用的标准具有以下定义:

uint8_t address;
uint8_t function;
uint8_t startAddressHi;
uint8_t startAddressLo;
uint8_t numberOfRegistersHi;
uint8_t numberOfRegistersLo;

能够将类型强制转换为 uint8_t 并一次性传输整个结构会很好,但问题是 startAddressHi 字节numberOfRegisters 的索引较低。我希望有一些鲜为人知的方法来改变定义的字节顺序:

typedef union{

    struct rturxfields{
        /* header */
        uint8_t address;
        uint8_t function;

        /* data */
        uint16_t startAddress;   // <= needs some special sauce
        uint16_t numberOfRegisters;
    }RtuRxFields;

    struct rturxfieldbytes{
        /* header */
        uint8_t address;
        uint8_t function;

        /* data */
        uint8_t startAddressHi;
        uint8_t startAddressLo;
        uint8_t numberOfRegistersHi;
        uint8_t numberOfRegistersLo;
    }RtuRxFieldBytes;

    uint8_t array[RX_FRAME_LENGTH];
}RtuRxFrame;

同样,按照定义,我的联合,字节顺序是关闭的。

我无法访问网络库中的 htons() 和类似内容。阅读更多之后,我想我会简单地摆脱 RtuRxFields 结构并创建实用函数 getStartAddress(RtuRxFrame* frame) 来干净地检索地址。

您可以做的一件事是使用 htonsntohs 在主机字节顺序(取决于机器)和网络字节顺序(大端)之间转换 16 位值。写入 16 位值时,通过 htons 传递它们以将字节按正确顺序排列。

myunion.RtuRxFields.numberOfRegisters = htons(5);

如果你没有权限访问这些函数,你可以使用位移位来获取高低字节,并在相关字段中分别写入:

uint16_t registers = 5;
...
myunion.RtuRxFieldBytes.numberOfRegistersHi = (registers >> 8) & 0xff;
myunion.RtuRxFieldBytes.numberOfRegistersLo = registers & 0xff;

由于结构填充,通过网络发送结构可能会出现问题。两台不同机器上的两个不同编译器可以使相同的结构在每台机器上具有不同的大小。有关详细信息,请参阅 this guide