c - _Bool 类型和严格的别名

标签 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 在第一种情况下。

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) 是否可靠,是吗?

关于c - _Bool 类型和严格的别名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52163870/

相关文章:

sql - Postgresql - boolean 字段的性能问题

c++ - C++17 中复制构造函数的继承

c++ - 为什么没有用户提供 cp/mv ctor 且具有虚拟函数但没有虚拟基的类没有 "trival cp/mv ctor"?

c - 加密一个简单的数组

javascript - 生成所有可能的真/假组合

C 指向数组的指针——我无法向自己解释的事情

c# - &= 运算符在 C# 中有什么作用?

c++ - 关于用括号括起来的声明类型是什么的问题

c - 字符到整数转换的巧妙之处

c - 即使我初始化了所有内容,我也无法弄清楚这个段错误。几乎相同的代码在另一个程序中运行良好。