将布尔设置为0安全吗?

Nei*_*irk 32 c++ memset language-lawyer

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

bool data[32];
memset(data, 0, sizeof(data));
Run Code Online (Sandbox Code Playgroud)

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

更一般地,是安全的memsetbool0,以使其价值false

是否保证可以在所有编译器上运行?或者我是否要求修复?

Lig*_*ica 24

这是法律保障吗?没有.

C++没有提到bool值的表示.

它是否由实际现实保证?是.

我的意思是,如果你想找到一个不代表布尔值false作为零序列的C++实现,我祝你好运.鉴于false必须隐式转换为0,true必须隐式转换为1,并且0必须隐式转换为false,并且0必须隐式转换为true......好吧,你以任何其他方式实现它都是愚蠢的.

这是否意味着"安全"是由你来决定的.

我通常不会这样说,但如果我遇到你的情况,我会很高兴让这张幻灯片.如果您真的担心,可以在可安装实际项目之前向可分发项添加测试可执行文件,以验证每个目标平台的前提条件.

  • 不,我不喜欢推特,但是当我评论时,它恰好是4个字符. (5认同)
  • Upvoted,虽然我希望有一些参考C++规范. (4认同)
  • 嗯......你是怎么做到的?我最后一次尝试发布一个简短的答案,它不会让我.(而且我确信这个简短的解释了这个问题.你真的可以解释一下,呃?) (2认同)
  • @CareyGregory:162个字符还不够?我想你一定不能享受Twitter. (2认同)
  • 这是肯定还是否定? (2认同)
  • @MatthieuM.:在某些平台上,测试值的特定位是否设置比测试值是否为非零更快.例如,许多嵌入式控制器具有"如果存储器位设置为跳转"指令,而不是"如果存储器非零则跳转"指令. (2认同)

Oli*_*pro 9

不,它不安全(或者更具体地说是便携式).但是,它可能工作凭借的事实,典型的实现将:

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

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

  • 小心; `bool data [32] = {false}`可以工作(读:它会;总是),但它也有点误导.它不等于`bool data [32] = {false,false,false,...}`,而是等于`bool data [32] = {false,0,0,0,0}`.这里真正的拯救恩典是"0"肯定会隐含地转换为"假",但它确实意味着命名"假"是一个红色的鲱鱼,[这可能会让某人有一天大惊喜]( http://stackoverflow.com/q/14797810/560648).因此,`bool data [32] = {}`将是我的偏好. (13认同)

Mar*_*k B 8

从3.9.1/7:

类型bool,char,char16_t,char32_t,wchar_t以及有符号和无符号整数类型统称为整数类型.整数类型的同义词是整数类型.整数类型的表示应使用纯二进制计算系统定义值.

鉴于此,我看不出任何可能的实现bool,并不代表所有0位的错误.

  • 那么你可以在*memory*中将false实现为1并将true实现为0.只要编译器巧妙地管理代码中所有必需的转换.它类似于空指针在内存中不一定是0. (4认同)
  • 不,标准无意限制像这样的`bool`的表示.`bool`值保证转换为'0`和`1`,但不保证与表示的'0`和`1`有任何关联. (2认同)

Sha*_*our 7

我相信这个没有具体说明,尽管看起来潜在的表示false可能都是零.Boost.Container也依赖于此(强调我的):

Boost.Container使用带有零值的std :: memset来初始化某些类型,就像在大多数平台中一样,这个初始化产生了具有改进性能的所需值初始化.

遵循C11标准,Boost.Container假定对于任何整数类型,所有位为零的对象表示应该是该类型中零值的表示.由于_Bool/wchar_t/char16_t/char32_t也是C中的整数类型,因此它将所有C++整数类型视为可通过std :: memset初始化.

他们指出这个C11引用的理由实际上来自C99缺陷:缺陷263:全零位表示增加了以下内容:

对于任何整数类型,所有位为零的对象表示应该是该类型中零值的表示.

那么这里的问题是假设正确,C和C++之间的整数兼容的底层对象表示是什么?提议解决C和C++之间关于整数的对象表示的差异试图在某种程度上回答这个问题,据我所知,这个问题没有得到解决.我在标准草案中找不到确凿的证据.我们有几种情况,它明确地链接到C标准的类型.章节3.9.1 [basic.fundamental]说:

[...]有符号和无符号整数类型应满足C标准第5.2.4.2.1节中给出的约束.

3.9 [basic.types]说:

类型T的对象的对象表示是由类型T的对象占据的N个无符号字符对象的序列,其中N等于sizeof(T).对象的值表示是保存类型T的值的位集.对于简单的可复制类型,值表示是对象表示中的一组位,用于确定值,该值是实现的一个离散元素 - 定义的值集.44

脚注44(不是规范性的)说:

目的是C++的内存模型与ISO/IEC 9899编程语言C的内存模型兼容.

标准草案中最远的用于指定bool的基础表示的部分是3.9.1:

类型bool,char,char16_t,char32_t,wchar_t以及有符号和无符号整数类型统称为整数类型.50整数类型的同义词是整数类型.积分类型的表示应使用纯二进制计算系统定义值.[例如:本国际标准允许2的补码,1的补码和积分类型的带符号幅度表示. - 末端的例子]

该部分还说:

bool类型的值为true或false.

但我们都知道的truefalse是:

布尔文字是关键字false和true.这样的文字是prvalues并且有类型bool.

而且我们知道他们是转换为0一个1:

bool类型的prvalue可以转换为int类型的prvalue,false变为零,true变为1.

但这让我们更接近于潜在的表现形式.

据我所知,除了填充位之外,标准引用实际基础位值的唯一位置是通过缺陷报告1796删除的:对于空字符,all-bits-zero是否是一个有意义的要求?:

目前尚不清楚便携式程序可以检查表示的位; 相反,它似乎仅限于检查与值表示相对应的数字位(3.9.1 [basic.fundamental]第1段).要求空字符值比较等于0或'\ 0'而不是指定表示的位模式可能更合适.

有更多的缺陷报告处理标准中的差距,关于值和对象表示之间的差异和差异.

实际上,我希望这可行,我不认为它是安全的,因为我们无法在标准中指出这一点.你是否需要改变它,不清楚,你显然需要进行一些非平凡的权衡.因此,假设它现在有效,那么问题是我们是否认为它可能会破坏各种编译器的未来版本,这是未知的.