【问题标题】:Detect endianness with type punning & padding bits使用类型双关语和填充位检测字节顺序
【发布时间】:2013-01-11 17:41:41
【问题描述】:

这是用于在运行时检测字节顺序的常用技巧,例如在 C FAQ 中看到的:

int x = 1;

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

根据我对标准的阅读,它不会导致未定义的行为,因为它没有违反严格的别名规则。

无论如何,只要unsigned char以外的整数类型可以包含填充位(如x),那么条件*(char *)x == 1即使是little-endian系统也不会出错吗?

在这种情况下,工会的解决方案是否更适合这样做?

【问题讨论】:

  • 在可以将任意填充散布到整数变量中的系统上,“字节顺序”的含义是什么? reinterpret-as-char 向您展示的只是数据的二进制表示。由给它起一个可爱的名字。
  • 这段代码的主要问题是它假设系统是小端或大端。如果两者都不是,它会将其错误归类为其中一个。

标签: c padding endianness


【解决方案1】:

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

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

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

【讨论】:

  • 没有陷阱表示的字符类型不是定义*(char *)&x 的原因。在 32 位 int 和 32 位 float 都没有填充位的实现中,*(int *)&f 仍然未定义。 *(char *)&x 不是未定义的原因是 C99 的第 6.5:7 条中的列表以“字符类型”结尾。该子句被称为“严格别名”子句,它是真实存在的,正如 google 或 StackOverflow 搜索应该显示的那样。
  • @PascalCuoq 没有陷阱表示的字符类型不是原因......但我从来没有想过这是原因。我没有引起混叠,因为 OP 已经正确地表示他的示例没有混叠违规。我提到没有明确的陷阱,即使有未指定的填充位,读取这些位也不能调用未定义的行为,因为它们不能是陷阱表示。
猜你喜欢
  • 1970-01-01
  • 2012-02-17
  • 2013-06-02
  • 1970-01-01
  • 1970-01-01
  • 2012-03-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多