设置int的所有字节为(无符号字符)0,保证表示零?
这不是build议的做法 (也不是未定义的行为 )的问题,而是关于将整数types的所有字节转换为
(unsigned char)0
值的c ++标准实际保证的内容。
问题(S)
在下面的代码片段中, if语句使用的expression式保证在c ++ 11中被评估为true ?
std::memset ( reinterpret_cast<char*> (&a), // int a; (unsigned char)0, sizeof (int) ); if (a == 0) { ... }
通过阅读C99和C ++ 11标准(本文后面的部分)的引用,我们发现C99明确保证所有位设置为0
的整数types将表示该types中的值0
。
我无法在C ++ 11标准中find这个保证。
- 有没有这样的保证?
- 前面的代码片段的结果是否是特定于实现的?
在C99(ISO / IEC 9899:1999)
5.2.1.2/1多字节字符
所有位为零的字节应被解释为与移位状态无关的空字符。 这样的字节不应该作为任何其他多字节字符的一部分出现。
6.2.6.2/1整数types
任何填充位的值都是未指定的。 45)符号位为零的有符号整数types的有效(无陷阱)对象表示是相应的无符号types的有效对象表示,并且表示相同的值。
对于任何整数types,所有位都为零的对象表示应该是该types中零值的表示。
在C ++ 11(ISO / IEC 14882:2011)
2.3 / 3字符集[lex.charset]
基本执行字符集和基本执行宽字符集应分别包含基本源字符集的所有成员,加上表示alert,backspace和回车的控制字符,加上空字符 (分别为空宽字符),其表示全部为零 。
C ++ 11
我认为有关的部分是
3.9.1 / 1在C ++ 11中
对于字符types,对象表示的所有位都参与到值表示中。 对于无符号字符types,值表示的所有可能位模式都表示数字。 这些要求不适用于其他types。
随着3.9.1 / 7
整体types的表示应使用纯二进制数字系统来定义值。
C11
6.2.6.2非常明确
对于除无符号字符以外的无符号整数types,对象表示的位应分为两组:值位和填充位(不需要后者中的任何一个)。 如果有N个比特位,则每个比特在1和2 N-1之间表示不同的幂2,以便该types的对象能够使用纯二进制表示来表示0到2 N-1的值; 这应该被称为价值表示。 任何填充位的值都是未指定的。
对于带符号整数types,对象表示的位应该被分成三组:值位,填充位和符号位。 不需要任何填充位; signed char不应该有任何填充位。 应该只有一个符号位。 每个有效位的位应该与相应无符号types的对象表示中的相同位具有相同的值(如果有符号types中有M个值位,无符号types中有N个,则M≤N)。 如果符号位为零,则不会影响结果值。 如果符号位是1,则应该用下列方法之一修改该值:
– 符号位0的相应值被否定(符号和大小);
– 符号位的值 – (2 M )(2的补码);
– 符号位的值 – (2 M – 1 )(1的补码)。
其中哪些适用是实现定义的,就像是具有符号位1和所有值位0(前两个)的值,还是符号位和所有值位1(用于补码)一样,是陷阱表示或正常值。 在符号和幅度以及补码的情况下,如果这种表示是正常值,则称其为负零。
Summmary
我认为这两个标准的意图是相同的。
-
char
,signed char
和unsigned char
都有参与该值的所有位 -
其他整数types可能有不参与该值的填充位 。 在他们错误的位模式可能意味着一个无效的价值。
-
解释是一个纯粹的二进制表示,其定义在上面的C11引用中被扩展了。
有两件事情可能不清楚:
-
可以-0( 符号和大小和_ones的补充)是C ++中的陷阱值
-
可以填充位之一是奇偶校验位(即,如果我们确保填充位未被修改,我们是否可以修改表示)
我会保守,对两者都是肯定的。
不。 例如,标准中没有任何内容禁止基于偏倚的表示,它只是要求它是二进制的。
是的,这是保证。
转换整数types的所有字节/位保证使得types的实例的值为零( 0
),如所提及的标准中的以下片段所述。
3.9.1 / 7基本types
整数types的同义词是整数types。 整体types的表示应使用纯二进制数字系统来定义值。 49
对于使用二进制数字0和1的整数的位置表示,其中由连续位表示的值是相加的,从1开始,并且乘以2的连续整数幂,除了可能对于具有最高位置的位。 (改编自美国国家信息处理系统词典 。)
不,我不相信这实际上是有保证的,但是相当模糊。
如果曾经有一个C ++实现,其中所有位不是 0
的表示,我会感到非常惊讶,但我相信这样的实现可能是符合(虽然是不正当的)。
首先考虑C99标准。 (是的,我知道,问题是关于C ++的;忍受着我。)它表示无符号整数types的对象表示的位被分成两组:值位和填充位(不需要任何填充位,大多数实现没有它们)。 值位组成纯粹的二进制表示; 填充位对该值没有贡献。 填充位的某些组合可能会生成陷阱表示 。
签名types是相似的,增加了一个单一的符号位。 带符号的types可以用符号和大小 ,或者二进制补码或者补码来表示 ,但是再次,任何填充位都不会影响该值,并且填充位的某些组合可以生成陷阱表示。
这个描述并不排除这样的可能性,例如,比char
更宽的整数types可能有一个必须总是1的填充位; 如果它是0,你有一个陷阱表示。 或者,也许更有说服力的是,它可能有一个奇怪的奇偶位。
C99标准发布后,第二个技术勘误增加了以下句子,这也出现在C11中。
对于任何整数types,所有位为零的对象表示应该是该types中零值的表示。
我会强调,这是作为规范性文本而不是作为脚注,这表明(但没有certificate),委员会成员认为,保证不是已经隐含在C99标准。
(C90对于整数types如何表示的描述要less得多,没有提到填充位,陷阱表示或二进制补码等等,我认为它给出的实现至less和C99一样灵活。
因此,从C99 TC2开始,C语言保证所有位的零是任何整数types的零表示。 在C99和C90中,这个保证没有说明。
那是C.那么C ++呢?
2011年的C ++标准似乎只提供了更多的整数types表示作为旧的1990 C标准的特异性。 它确实需要使用2的补码,1的补码或有符号的幅度来表示签名types。 它也需要一个“纯粹的二进制数字系统”。 它没有提到“陷阱表示”,也没有讨论除了比特字段的情况下的填充比特。
因此,在C90和TC2之前的C99中,至less在理论上全零位是一个整数types的陷阱表示。 C ++标准对整数types的要求与C90和C99非常相似。 它确实需要一个“纯粹的二进制表示”,但是我认为这一点在C99中只适用于数值位; 尽pipeC ++没有提到填充位,但并不禁止它们。
再次,这主要是理论上的兴趣(因此是“语言律师”的标签)。 C委员会可以自由地强制要求全零位必须是零表示,因为所有的实现已经满足它。 这几乎肯定适用于C ++。