将 memset bool 设置为 0 安全吗?

Is it safe to memset bool to 0?

假设我有一些 legacy 代码,除非发现 bug,否则无法更改,并且它包含以下代码:

bool data[32];
memset(data, 0, sizeof(data));

这是将数组中的所有 bool 设置为 false 值的安全方法吗?

更一般地说,memset a bool0 以使其值 false 安全吗?

是否保证适用于所有编译器?还是我请求修复?

有法律保障吗?编号

C++ 未提及 bool 值的表示。

有实际保证吗?是的

我的意思是,如果您希望找到不将布尔值 false 表示为零序列的 C++ 实现,我祝您好运。鉴于 false 必须隐式转换为 0,并且 true 必须隐式转换为 1,并且 0 必须隐式转换为 false,并且非 0 必须隐式转换为 true ……好吧,你以任何其他方式实现它都是愚蠢的。

是否意味着 "safe" 由您决定。

我通常不这么说,但如果我是你的情况,我很乐意让这个幻灯片。如果您真的很担心,您可以在您的可分发文件中添加一个测试可执行文件,以在安装实际项目之前验证每个目标平台上的先决条件。

从 3.9.1/7 开始:

Types bool , char , char16_t , char32_t , wchar_t , and the signed and unsigned integer types are collectively called integral types. A synonym for integral type is integer type . The representations of integral types shall define values by use of a pure binary numeration system.

鉴于此,我看不到 bool 的任何可能实现都不会将 false 表示为全 0 位。

不。 它不安全(或更具体地说,便携)。但是,由于您的典型实施将:

,因此它可能 有效
  1. 用 0 表示布尔值(实际上,C++ 规范要求它)
  2. 生成一个memset()可以处理的元素数组。

但是,最佳实践将要求使用 bool data[32] = {false} - 此外,这可能会释放编译器以在内部以不同方式表示结构 - 因为使用 memset() 可能会导致它生成 32 字节数组的值而不是,说,一个 4 字节,将很好地适合你的平均 CPU 寄存器。

更新

P1236R1: Alternative Wording for P0907R4 Signed Integers are Two's Complement 表示如下:

As per EWG decision in San Diego, deviating from P0907R3, bool is specified to have some integral type as its underlying type, but the presence of padding bits for "bool" will remain unspecified, as will the mapping of true and false to values of the underlying type.

原答案

我相信这是未指定的,尽管 false 的基本表示可能全为零。 Boost.Container relies on this as well强调我的):

Boost.Container uses std::memset with a zero value to initialize some types as in most platforms this initialization yields to the desired value initialization with improved performance.

Following the C11 standard, Boost.Container assumes that for any integer type, the object representation where all the bits are zero shall be a representation of the value zero in that type. Since _Bool/wchar_t/char16_t/char32_t are also integer types in C, it considers all C++ integral types as initializable via std::memset.

他们指出的这个 C11 引用作为基本原理实际上来自 C99 缺陷:defect 263: all-zero bits representations 添加了以下内容:

For any integer type, the object representation where all the bits are zero shall be a representation of the value zero in that type.

那么这里的问题是假设是否正确,整数的底层对象表示是否在 C 和 C++ 之间兼容? 提案 Resolving the difference between C and C++ with regards to object representation of integers 试图在某种程度上回答这个问题,据我所知还没有解决。我在标准草案中找不到确凿的证据。我们有几个案例,它在类型方面明确链接到 C 标准。第 3.9.1 [basic.fundamental] 部分说:

[...] The signed and unsigned integer types shall satisfy the constraints given in the C standard, section 5.2.4.2.1.

3.9 [basic.types] 表示:

The object representation of an object of type T is the sequence of N unsigned char objects taken up by the object of type T, where N equals sizeof(T). The value representation of an object is the set of bits that hold the value of type T. For trivially copyable types, the value representation is a set of bits in the object representation that determines a value, which is one discrete element of an implementation-defined set of values.44

其中脚注 44(不规范)说:

The intent is that the memory model of C++ is compatible with that of ISO/IEC 9899 Programming Language C.

标准草案在指定 bool 的基础表示方面最远的地方在 3.9.1:

部分

Types bool, char, char16_t, char32_t, wchar_t, and the signed and unsigned integer types are collectively called integral types.50 A synonym for integral type is integer type. The representations of integral types shall define values by use of a pure binary numeration system.51 [ Example: this International Standard permits 2’s complement, 1’s complement and signed magnitude representations for integral types. —end example ]

该部分还说:

Values of type bool are either true or false.

但我们对 truefalse 的了解是:

The Boolean literals are the keywords false and true. Such literals are prvalues and have type bool.

我们知道它们可以转换为 01:

A prvalue of type bool can be converted to a prvalue of type int, with false becoming zero and true becoming one.

但这并没有让我们更接近底层表示。

据我所知,标准引用除填充位之外的实际基础位值的唯一地方已通过 defect report 1796: Is all-bits-zero for null characters a meaningful requirement? :

删除

It is not clear that a portable program can examine the bits of the representation; instead, it would appear to be limited to examining the bits of the numbers corresponding to the value representation (3.9.1 [basic.fundamental] paragraph 1). It might be more appropriate to require that the null character value compare equal to 0 or '[=28=]' rather than specifying the bit pattern of the representation.

还有更多 defect reports 处理标准中关于什么是位以及值和对象表示之间的差异的差距。

实际上,我希望它能起作用,但我认为它不安全,因为我们无法在标准中明确这一点。您是否需要更改它,不清楚,您显然需要进行重要的权衡。所以假设它现在可以工作,问题是我们是否认为它可能会破坏各种编译器的未来版本,这是未知的。