_Bool 类型和严格的别名

_Bool type and strict aliasing

我试图编写一些宏以确保 _Bool 的类型安全使用,然后对我的代码进行压力测试。为了邪恶的测试目的,我想出了这个肮脏的黑客:

_Bool b=0;
*(unsigned char*)&b = 42;

鉴于 _Bool 在实现 sizeof(_Bool)==1) 上是 1 个字节,我看不出这个 hack 如何违反 C 标准。它不应该是严格的别名违规。

然而当运行这个程序通过各种编译器时,我遇到了问题:

#include <stdio.h>

int main(void)
{
  _Static_assert(sizeof(_Bool)==1, "_Bool is not 1 byte");

  _Bool b=0;
  *(unsigned char*)&b = 42;
  printf("%d ", b);
  printf("%d", b!=0 );

  return 0;
}

(代码依赖于 printf 隐式默认参数提升为 int

一些版本的 gcc 和 clang 输出 42 42,其他版本输出 0 0。即使禁用优化。我本以为 42 1

编译器似乎假设 _Bool 只能是 10,但同时它在第一种情况下愉快地打印 42 .

Q1:这是为什么?上面的代码是否包含未定义的行为?

Q2:sizeof(_Bool)的可靠性如何? C17 6.5.3.4 根本没有提到_Bool

Q1: Why is this? Does the above code contain undefined behavior?

是的,确实如此。该商店有效,但随后将其读取为 _Bool 无效。

6.2.6 Representations of types

6.2.6.1 General

5 Certain object representations need not represent a value of the object type. If the stored value of an object has such a representation and is read by an lvalue expression that does not have character type, the behavior is undefined. [...]

Q2: How reliable is sizeof(_Bool)? C17 6.5.3.4 does not mention _Bool at all.

它会可靠地告诉您存储一个 _Bool 所需的字节数。 6.5.3.4也没有提到int,但你不是在问sizeof(int)靠谱吗?