这不是推荐做法(也不是未定义的行为)的问题,而是 c ++ -standard实际保证的内容将整数类型的所有字节都转换为
(unsigned char)0
的值。
在下面的代码段中, if-statement 使用的表达式是否保证在c++11中被评估为 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标准中找到此保证。
5.2.1.2/1多字节字符
所有位为零的字节应解释为空字符 独立于班次状态。这样的字节不应作为任何一部分出现 其他多字节字符。
6.2.6.2/1整数类型
任何填充位的值都未指定。 45)有效 (非陷阱)有符号整数类型的对象表示 符号位为零是对应的有效对象表示 无符号类型,并且应代表相同的值。
对于任何整数 类型,所有位为零的对象表示应为a 表示该类型的零值。
2.3 / 3字符集[lex.charset]
基本执行字符集和基本执行 宽字符集应各自包含基本的所有成员 源字符集,加上代表警报的控制字符, 退格和回车,再加上空字符(分别为 null宽字符),其表示具有全零位。
答案 0 :(得分:14)
我认为相关部分是
3.9.1 / 1在C ++ 11中
对于字符类型,对象表示的所有位都参与其中 在价值表示中。对于无符号字符类型,值表示的所有可能位模式表示数字。这些要求不适用于其他类型。
与3.9.1 / 7一起
整数类型的表示 应使用纯二进制计算系统定义值。
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 负零。
我认为两种标准的意图相同。
char
,signed char
和unsigned 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 ++。