我如何在 C 中表示给定的内存布局,而不是数学值?

How can I represent a given memory layout, rather than mathematical value, in C?

呃,字节顺序。问题是 0x65736c6166 的内存布局在不同的字节序上会有所不同。这是因为数字是由值定义的。我常量末尾的 66 将在小端系统上进入第一个字节,在大端系统上进入最后一个字节,但数字是相同的。我如何通过内存布局而不是值来定义数字变量,所以在不同的字节序上,它们的内存布局将保持不变,但它们的值将完全不同?并且需要将其视为编译时常量。

虽然它不是整数常量表达式,但您可以定义例如:

#define X ((union { unsigned char r[8]; uint64_t v; }){ 0x65, 0x73, 0x6c, 0x61, 0x66 }.v)

X 现在扩展为 uint64_t 类型的表达式,根据其表示而不是其值定义。

How can I define number variables by memory layout rather than by value, so on different endians, their memory layout will stay the same, but their value will be completely different?

好吧,只有两个字节序要处理。您可以编写一个宏函数,将主机字节顺序转换为您想要的字节顺序,并在使用常量时使用此类宏。

#include <assert.h>
#include <string.h>
#include <inttypes.h>

// Copied from glibc bits/byteswap.h
#define bswap_constant_64(x) \
  ((((x) & 0xff00000000000000ull) >> 56)    \
   | (((x) & 0x00ff000000000000ull) >> 40)  \
   | (((x) & 0x0000ff0000000000ull) >> 24)  \
   | (((x) & 0x000000ff00000000ull) >> 8)   \
   | (((x) & 0x00000000ff000000ull) << 8)   \
   | (((x) & 0x0000000000ff0000ull) << 24)  \
   | (((x) & 0x000000000000ff00ull) << 40)  \
   | (((x) & 0x00000000000000ffull) << 56))

// __BYTE_ORDER__ and __ORDER_BYTE_ORDER__ are macros defined by gcc
// use different check when compiling with a compiler that doesnt define them
#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
#define HTOLE64(x)  (x)
#else
#define HTOLE64(x)  bswap_constant_64(x)
#endif

// yes a constant expression
static unsigned long long mynumber = HTOLE64(0x65736c6166ull);

int main() {
    char bytes[sizeof(mynumber)];
    memcpy(bytes, &mynumber, sizeof(mynumber));
    // works on any endianess
    assert(bytes[0] == 0x66);
    assert(bytes[1] == 0x61);
}

Tested on godbolt.