使用类型转换和填充位检测字节序

4
以下是需要翻译的内容:

这里是一种常见的在运行时检测字节序(endianness)的技巧,例如在C FAQ中看到:

int x = 1;

if (*(char *)&x == 1)
{
  /* little-endian */
}
else
{
  /* big-endian */
}

根据我对标准的阅读,它不会导致未定义行为,因为它没有违反严格别名规则。
无论如何,只要整数类型(除了unsigned char)可以包含填充位(例如x),即使在小端系统上,条件*(char*)x == 1也可能是错误的。
在这种情况下,使用联合来解决这个问题是否更好呢?

1
对于可以将任意填充插入整数变量的系统,“字节序”是什么意思?重新解释为字符所显示的只是数据的二进制表示。由来为其指定一个可爱的名称。 - Kerrek SB
1
这段代码的主要问题在于它假设系统是小端或大端。如果不是这两种情况,它会错误地将其归类为其中一种。 - Chris Dodd
1个回答

4

我不确定当存在填充位时,字节序是否真的有意义,但除此之外,您是正确的,条件可能是错误的。至少您没有调用未定义的行为,因为字符类型没有陷阱表示。

否则,您可以使用精确宽度整数类型(如uint32_t等)。尽管这些类型是可选的,但它们保证没有填充位。

请注意,signed char也不能有填充位。


没有陷阱表示的字符类型并不是 *(char *)&x 被定义的原因。在一个既没有填充位的32位‘int’和32位‘float’的实现中,*(int *)&f 仍然未定义。 *(char *)&x 不是未定义的原因是因为C99条款6.5:7中的列表以“字符类型”结尾。这个条款被称为“严格别名”条款,它是真实存在的,可以通过Google或StackOverflow搜索证明。 - Pascal Cuoq
@PascalCuoq 字符类型没有陷阱表示不是原因... 但我从未意味着这是原因。我没有提到别名,因为OP已经正确地说出了他的示例中没有别名违规。我提到没有陷阱来明确即使存在未指定的填充位,读取这些位也不能调用未定义的行为,因为它们不能是陷阱表示。 - ouah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接