4

以下byte在 big-endian 上设置为 1,在 little-endian 上设置为 0。

uint16_t word = 0x0001;
uint8_t byte = *(((uint8_t *)&word) + 1);

有什么方法可以获取跨平台安全的低字节或高字节的地址吗?

4

2 回答 2

3

也许是这样的:

int isBigEndian()
{
    uint16_t word = 0x0001;
    return *(((uint8_t *)&word) + 1);
}

void main()
{
    uint16_t word = 0x0001;
    uint8_t byte = *(((uint8_t *)&word) + isBigEndian());
    printf("%d\n", byte);
}

为避免每次在运行时检查,您可以使用 a#define并使用assert. 像这样:

#define BIG_ENDIAN 0  // 0 or 1 depending on what the platform is

void main()
{
    assert(isBigEndian() == BIG_ENDIAN);  // Make sure #define is OK
    // more code...
}

在代码的其他地方,您可以BIG_ENDIAN根据平台使用符号来编译代码。所以除了assert.

于 2021-07-03T07:00:56.897 回答
3

从 C99 开始,代码可以使用复合文字来查找 MSByte 地址偏移量。
让编译器形成高效的代码。

下面使用一个 4 字节的示例来帮助说明对 big、little 和PDP endian的遵守情况。

int main() {
  uint32_t word = 0x12345678;
  printf("%p\n", (void*)&word);
  for (unsigned i=0; i<sizeof word; i++) printf("%x\n", ((uint8_t*) &word)[i]);

  uint8_t *msbyte_address = ((uint8_t*) &word) + //
  //  v----------------------------------------------------v compound literal
      ( union { uint32_t u32; uint8_t u8[4]; }) {0x00010203}.u8[0];
  //                                    value at 1st byte    ^---^

  printf("%p\n", (void*)msbyte_address);
}

示例输出(小端)

0xffffcbfc
78
56
34
12
0xffffcbff

为了uint16_t

  uint16_t word = 0x1234;
  uint8_t *msbyte_address = ((uint8_t*) &word) + 
      ( union { uint16_t u16; uint8_t u8[2]; }) {0x0001}.u8[0];
于 2021-07-03T10:12:33.773 回答