首页 文章

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

提问于
浏览
43

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


问题

在下面的代码片段中,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明确 guarantees ,所有位设置为 0 的整数类型将表示该类型中的值 0 .

I cannot find this guarantee in the C++11 standard.

  • 没有这样的保证吗?

  • 上一个代码段的结果是否真的特定于实现?



在C99(ISO / IEC 9899:1999)

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

6.2.6.2/1整数类型任何填充位的值都是未指定的.45)符号位为零的有符号整数类型的有效(非陷阱)对象表示是相应无符号类型的有效对象表示,并代表相同的 Value . 对于任何整数类型,所有位为零的对象表示应该是该类型中零值的表示 .



在C 11(ISO / IEC 14882:2011)

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

4 回答

  • 2

    C 11

    我认为相关的部分是

    3.9.1 / 1在C 11中

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

    随着3.9.1 / 7

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

    C11

    6.2.6.2非常明确

    对于unsigned char以外的无符号整数类型,对象表示的位应分为两组:值位和填充位(不需要后者中的任何一个) . 如果有N个值位,则每个位应表示1和2N-1之间的2的不同幂,因此该类型的对象应能够使用纯二进制表示来表示0到2N-1的值;这应该被称为 Value 表示 . 任何填充位的值都未指定 . 对于有符号整数类型,对象表示的位应分为三组:值位,填充位和符号位 . 不需要任何填充位; signed char不应有任何填充位 . 应该只有一个符号位 . 作为值位的每个位应具有与相应无符号类型的对象表示中的相同位相同的值(如果有符号类型中有M个值位且无符号类型中有N,则M≤N) . 如果符号位为零,则不应影响结果值 . 如果符号位为1,则应以下列方式之一修改该值: - 符号位0的相应值被否定(符号和幅度); - 符号位的值为 - (2M)(二进制补码); - 符号位的值为 - (2M - 1)(补码) . 这些适用中的哪一个是实现定义的,将符号位1和所有值位0(对于前两个),或者符号位和所有值位1(对于1'补码)的值是否是陷阱表示或正常值 . 在符号和幅度以及1'补码的情况下,如果该表示是正常值,则称为负零 .

    Summmary

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

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

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

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

    有两点可能不清楚:

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

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

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

  • 2

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

  • 14

    Yes, it's guaranteed.

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


    3.9.1 / 7基本类型整数类型的同义词是整数类型 . 整数类型的表示应使用纯二进制计算系统定义值

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

  • 0

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

    如果有一个C实现,其中all-bits-zero不是 0 的表示,我会感到非常惊讶,但我相信这样的实现可能符合(虽然有悖常理) .

    设's start by considering the C99 standard. (Yes, I know, the question is about C++; bear with me.) It says that the bits of the object representation of an unsigned integer type are divided into two groups: value bits and padding bits (there needn't是任何填充位,大多数实现都没有它们 . 值位构成纯二进制表示;填充位对该值没有贡献 . 填充位的某些组合可能会生成陷阱表示 .

    签名类型相似,增加了单个符号位 . 有符号类型可以使用符号和幅度,或二进制补码或一个补码来表示 - 但同样,任何填充位都不会对该值产生影响,并且填充位的某些组合可以生成陷阱表示 .

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

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

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

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

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

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

    那是C. C怎么样?

    与旧的1990 C标准相比,2011 C标准似乎只提供了关于整数类型表示的更多特异性 . 它确实需要使用2 's complement, 1' s补码或带符号幅度表示有符号类型 . 它还需要"pure binary numeration system" . 它没有提到"trap representations",也没有讨论填充位,除了在位域的上下文中 .

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

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

相关问题