将int的所有字节设置为(unsigned char)0,保证代表零?

Fil*_*efp 43 c++ language-lawyer c++11

这不是建议的做法(也不是未定义的行为),而是关于将整数类型的所有字节转换为值的c ++标准实际上保证的内容(unsigned char)0.


问题

在下面的代码片段中,if-statement使用的表达式是否保证在被评估为true

std::memset (
  reinterpret_cast<char*> (&a), // int a;
  (unsigned char)0,
  sizeof (int)
);

if (a == 0) {
  ...
}
Run Code Online (Sandbox Code Playgroud)

通过阅读C99和C++ 11标准中的引文(在本文中进一步说明),我们发现C99明确保证所有位设置为的整数类型0将表示该0类型中的值.

我在C++ 11标准中找不到这种保证.

  • 没有这样的保证吗?
  • 上一个代码段的结果是否真的特定于实现?


在C99(ISO/IEC 9899:1999)

5.2.1.2/1多字节字符

所有位为零的字节应被解释为与移位状态无关的空字符.这样的字节不应作为任何其他多字节字符的一部分出现.

6.2.6.2/1整数类型

任何填充位的值都是未指定的.45)符号位为零的有符号整数类型的有效(非陷阱)对象表示是相应无符号类型的有效对象表示,并且应表示相同的值.

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



在C++ 11(ISO/IEC 14882:2011)中

2.3/3字符集[lex.charset]

基本执行字符集和基本执行宽字符集应各自包含基本源字符集的所有成员,以及表示alert,backspace和回车符的控制字符,以及空字符(分别为null宽字符),其表示具有全零位.

APr*_*mer 14

C++ 11

我认为相关的部分是

3.9.1/1在C++ 11中

对于字符类型,对象表示的所有位都参与值表示.对于无符号字符类型,值表示的所有可能位模式表示数字.这些要求不适用于其他类型.

随着3.9.1/7

整数类型的表示应使用纯二进制计算系统定义值.

C11

6.2.6.2非常明确

对于unsigned char以外的无符号整数类型,对象表示的位应分为两组:值位和填充位(不需要后者中的任何一个).如果有N个值位,则每个位应表示1和2 N-1之间的2的不同幂,因此该类型的对象应能够使用纯二进制表示来表示0到2 N-1的值; 这应该被称为价值表示.任何填充位的值都未指定.

对于有符号整数类型,对象表示的位应分为三组:值位,填充位和符号位.不需要任何填充位; signed char不应有任何填充位.应该只有一个符号位.作为值位的每个位应具有与相应无符号类型的对象表示中的相同位相同的值(如果有符号类型中有M个值位且无符号类型中有N,则M≤N).如果符号位为零,则不应影响结果值.如果符号位为1,则应以下列方式之一修改该值:

- 符号位0的相应值被否定(符号和幅度);

- 符号位的值为 - (2 M)(二进制补码);

- 符号位的值为 - (2 M - 1)(1'补码).

这些适用中的哪一个是实现定义的,将符号位1和所有值位0(对于前两个),或者符号位和所有值位1(对于1'补码)的值是否是陷阱表示或正常值.在符号和幅度以及1'补码的情况下,如果该表示是正常值,则称为负零.

Summmary

我认为两种标准的意图都是一样的.

  • char,signed charunsigned char让所有位参与该值

  • 其他整数类型可能具有不参与该值的填充位.它们中的错误位模式可能意味着无效值.

  • 解释是一个纯二进制表示,其定义在上面的C11引用中扩展.

有两点可能不清楚:

  • can -0(用于符号和幅度以及_ones'补码)是C++中的陷阱值

  • 其中一个填充位是奇偶校验位(即如果我们确保填充位不被修改,我们可以修改表示)

我会保守,对两者都假设是.