_布尔类型和严格的别名

时间:2018-09-04 10:09:20

标签: c boolean language-lawyer c11 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。 / p>

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

Q2:sizeof(_Bool)有多可靠? C17 6.5.3.4根本没有提到_Bool

1 个答案:

答案 0 :(得分:8)

  

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

是的,确实如此。存储有效,但随后读取为_Bool无效。

  

6.2.6类型的表示形式

     

6.2.6.1常规

     

5某些对象表示形式不必表示对象类型的值。如果对象的存储值具有这种表示形式,并且由不具有字符类型的左值表达式读取,则该行为是不确定的。 [...]

  

Q2:sizeof(_Bool)有多可靠? C17 6.5.3.4根本没有提到_Bool

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