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

时间:2012-06-21 12:30:00

标签: c++ c++11 language-lawyer

  

这不是推荐做法(也不是未定义的行为)的问题,而是 c ++ -standard实际保证的内容将整数类型的所有字节都转换为(unsigned char)0的值。


问题

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

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

if (a == 0) {
  ...
}

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

我无法在C ++ 11标准中找到此保证。

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


在C99(ISO / IEC 9899:1999)

  

5.2.1.2/1多字节字符

     

所有位为零的字节应解释为空字符   独立于班次状态。这样的字节不应作为任何一部分出现   其他多字节字符。

  

6.2.6.2/1整数类型

     

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

     

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



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

  

2.3 / 3字符集[lex.charset]

     

基本执行字符集和基本执行   宽字符集应各自包含基本的所有成员   源字符集,加上代表警报的控制字符,   退格和回车,再加上空字符(分别为   null宽字符),其表示具有全零位

4 个答案:

答案 0 :(得分:14)

C ++ 11

我认为相关部分是

3.9.1 / 1在C ++ 11中

  

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

与3.9.1 / 7一起

  

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

C11

6.2.6.2非常明确

  

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

     

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

     

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

     

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

     

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

     

其中哪一个适用于实现定义,以及符号位为1的值   并且所有值位为零(对于前两个),或者对于符号位和所有值位1(对于“补码”),是陷阱表示或正常值。在签名和   幅度和1'补码,如果这个表示是一个正常值,它被称为a   负零。

Summmary

我认为两种标准的意图相同。

  • charsigned charunsigned char所有位都参与了值

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

  • 解释是纯二进制表示,其定义在上面的C11引文中扩展。

可能不清楚的两件事:

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

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

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

答案 1 :(得分:2)

是的,这是有保证的。

保证整数类型的所有字节/位都使该类型的实例具有零(0)的值,如下面提到的标准的片段所述。


  

3.9.1 / 7基本类型

     

整数类型的同义词是整数类型。 的表示   整数类型应使用纯二进制计数定义值   系统 49

  

49 使用二进制数字0和1的整数的位置表示,其中由连续位表示的值是加法的,以1开始,并乘以连续的积分幂2,除了位置最高的位置。 (改编自美国国家信息处理系统词典。)

答案 2 :(得分:2)

不。例如,标准中没有任何内容禁止基于偏差的表示,它只强制它是二进制的。

答案 3 :(得分:0)

没有。我不相信它实际上有保证,但它相当含糊。

如果有一个C ++实现,其中所有位零表示0,那么我会感到非常感到惊讶,但是我相信这样的实现可能符合(虽然有悖常理)。

让我们从考虑C99标准开始。 (是的,我知道,问题是关于C ++;请耐心等待。)它表示无符号整数类型的对象表示的位被分为两组:值位和填充位(不需要任何填充)比特,大多数实现都没有它们。值位构成纯二进制表示;填充位对该值没有贡献。填充位的某些组合可能会生成陷阱表示

签名类型类似,添加了单个符号位。签名类型可以使用符号和幅度,或二进制补码一个补码来表示 - 但同样,任何填充位都没有贡献对于该值,填充位的某些组合可以生成陷阱表示。

此描述不排除例如宽于char的整数类型可能具有必须始终为1的单个填充位的可能性;如果它为0,则表示陷阱。或者,也许更合理的是,它可能有奇数奇偶校验位。

C99标准出版后,第二份技术勘误表增加了以下句子,该句也出现在C11中。

  

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

我要强调的是,这是作为规范性文本添加的,而非脚注,这表明(但未证明)委员会成员认为保证并未隐含在C99标准中。

(C90对于如何表示整数类型的具体要少得多。它没有提到填充位,陷阱表示或二进制补码等。我认为它给出的实现至少与C99一样灵活。)< / p>

因此从C99 TC2开始,C语言保证all-bits-zero对任何整数类型都表示为零。在C99和C90中,没有说明该保证。

那是C. C ++怎么样?

与旧的1990 C标准相比,2011 C ++标准似乎只提供了关于整数类型表示的更多特异性。它确实需要使用2的补码,1的补码或有符号的幅度来表示有符号的类型。它还需要一个“纯二进制计算系统”。它没有提到“陷阱表示”,也没有讨论填充位,除了在位域的上下文中。

因此,在C90和TC2之前的C99中,至少在理论上,所有位零都可以成为整数类型的陷阱表示。 C ++标准对整数类型的要求与C90和C99非常相似。它确实需要一个“纯二进制表示”,但我认为这适用于在C99中,只适用于值位;虽然C ++没有提到填充位,但它并没有禁止它们。

同样,这主要是理论上的兴趣(因此是“语言 - 律师”标签)。 C委员会可以自由地强制要求所有位零必须表示为零,因为所有实现已经满足它。这几乎肯定适用于C ++。