_Bool类型和严格别名

问题描述 投票:7回答:1

我试图编写一些宏来安全地使用_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

c boolean language-lawyer c11 strict-aliasing
1个回答
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)是否可靠,是吗?

© www.soinside.com 2019 - 2024. All rights reserved.