_Bool类型和严格别名

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了_Bool类型和严格别名相关的知识,希望对你有一定的参考价值。

我试图编写一些宏来安全地使用_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:这是为什么?上面的代码是否包含未定义的行为?

是的,它确实。商店是有效的,但后来读作_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)是否可靠,是吗?

以上是关于_Bool类型和严格别名的主要内容,如果未能解决你的问题,请参考以下文章

C++ 构建警告:取消引用类型双关指针将破坏严格别名规则

c中的严格别名和数组

严格别名规则“-fstrict-aliasing”和“-fno-strict-aliasing”及类型双关

这真的违反了严格的别名规则吗?

这真的违反了严格的别名规则吗?

小对象堆栈存储、严格别名规则和未定义行为