C 中的字节顺序宏

Endianness macro in C

我最近看到这个 post 关于 C 中的字节顺序宏,我真的无法理解第一个答案。

Code supporting arbitrary byte orders, ready to be put into a file called order32.h:

#ifndef ORDER32_H
#define ORDER32_H

#include <limits.h>
#include <stdint.h>

#if CHAR_BIT != 8
#error "unsupported char size"
#endif

enum
{
    O32_LITTLE_ENDIAN = 0x03020100ul,
    O32_BIG_ENDIAN = 0x00010203ul,
    O32_PDP_ENDIAN = 0x01000302ul
};

static const union { unsigned char bytes[4]; uint32_t value; } o32_host_order =
    { { 0, 1, 2, 3 } };

#define O32_HOST_ORDER (o32_host_order.value)

#endif

You would check for little endian systems via

O32_HOST_ORDER == O32_LITTLE_ENDIAN

我确实了解一般的字节顺序。这就是我对代码的理解:

  1. 创建小、中、大端顺序的示例。
  2. 将测试用例与小端、中端和大端示例进行比较,并确定主机的类型。

我不明白的有以下几个方面:

  1. 为什么需要联合来存储测试用例uint32_t 不保证能够根据需要容纳 32 bits/4 字节吗?赋值 { { 0, 1, 2, 3 } } 是什么意思?它将值分配给联合,但为什么 strange 标记带有两个大括号?
  2. 为什么要检查 CHAR_BIT?一条评论提到检查 UINT8_MAX 会更有用吗?为什么 char 甚至在这里使用,当它不能保证是 8 位宽时?为什么不直接使用 uint8_t?我发现 this link 到 Google-Devs github。他们不依赖这张支票...有人可以详细说明吗?

为什么需要联合来存储测试用例?

测试的重点是使用数组将创建的魔法值作为数组的别名。

uint32_t 是否保证能够根据需要容纳 32 bits/4 个字节?

嗯,或多或少。它 但除 32 位外没有任何保证。它只会在您永远不会遇到的一些非常边缘的架构上失败。

赋值 { { 0, 1, 2, 3 } } 是什么意思?它将值分配给联合,但为什么带有两个大括号的奇怪标记?

内括号用于数组。

为什么检查 CHAR_BIT?

因为这是实际的保证。如果那不爆炸,一切都会好起来的。

一条评论提到检查 UINT8_MAX? 为什么在这里使用 char 会更有用,因为它不能保证是 8 位宽?

因为事实上,现在一直如此。

为什么不直接使用 uint8_t? 我发现这个 link 给 Google-Devs github。他们不依赖这张支票...有人可以详细说明吗?

许多其他选择也可以。

初始化有两组大括号,因为内大括号初始化 bytes 数组。所以 byte[0] 是 0,byte[1] 是 1,等等

联合允许 uint32_tchar 数组位于相同的字节上,并以任何机器的字节顺序进行解释。所以如果机器是小端,0在低位字节,3value的高位字节。反之,如果机器是big endian,0value.

的高位字节,3在低位字节

{{0, 1, 2, 3}} 是联合的初始值设定项,这将导致 bytes 组件被 [0, 1, 2, 3].

填充

现在,由于 bytes 数组和 uint32_t 占用相同的 space,您可以读取与本机 32 位整数相同的值。该整数的值向您显示数组是如何洗牌的——这实际上意味着您使用的是哪种字节序系统。

这里只有 3 种流行的可能性 - O32_LITTLE_ENDIANO32_BIG_ENDIANO32_PDP_ENDIAN

至于 char / uint8_t - 我不知道。我认为只使用 uint_8 而不检查更有意义。