C++标准是否要求有符号整数正好有一个符号位

Does the C++ standard requires signed integers to have exactly one sign bit?

本文关键字:符号 整数 有一个 标准 是否 C++      更新时间:2023-10-16

考虑C++的基本有符号整数类型,即:signed charshort intintlong intlong long int,当前的C++标准对其底层位表示有什么要求?

对其位表示的约束是否指定它们应包括:

  • 可选填充位
  • 强制值位
  • 一个强制符号位,正值0,负值1
  • 如果存在,则符号位应为最高有效位

这是真的吗?如果不是,那么有什么问题?我正在寻找证明或反驳这一点的标准中的报价。

编辑:我问这个问题,因为在C中,标准说:

6.2.6.2.2:

对于有符号整数类型,对象表示的位应 分为三组:值位、填充位和符号 位。不需要任何填充位;签名字符不应有 任何填充位。应正好有一个符号位。每个位 是值位应与对象中的相同位具有相同的值 表示相应的无符号类型(如果有 M 值有符号类型中的位和无符号类型中的 N 位,然后 M ≤ N ).如果符号位为零,则不会影响结果值。 如果符号位为 1,则应在其中一个 以下方式:

  • 符号位为 0 的相应值为反(符号和幅度);
  • 符号位的值为 −(2^M)(二进制补码);
  • 符号位的值为 −(2^M − 1)(一补码)。

其中哪一个适用是实现定义的,就像 符号位为 1 且所有值的值是否为零(对于 前两个),或带有符号位和所有值位 1(对于 1 的 补码),是陷阱表示形式或正常值。在这种情况下 符号和大小以及 1 的补语,如果这个表示是 正常值称为负零。

所以我想知道C++中是否存在类似的东西

这是 C++11 对有符号整数类型的表示所说的话:

C++11 N3337 3.9.1 [基本基础] P7:

整型的表示应使用纯二进制数字系统定义值。49 [ 示例:本国际标准允许积分类型的 2 补码、1 补码和有符号量级表示。示例 ]

其中脚注49如下:

  1. 使用二进制数字 0 和 1 的整数的位置表示形式,其中由连续位表示的值是累加的,从 1 开始,乘以 2 的连续积分幂,但可能具有最高值的位除外位置。(改编自美国国家信息处理系统词典。

因此,C++允许与C相同的三个选项,以及满足脚注49的任何其他选项。这是 C 允许的超集。然而,到脚注49时,只允许最高的位具有特殊含义。

更新 2021-10-11

C++20 引入了有关允许的有符号整数表示形式的更改。

N4860 [basic.fundamental/p3] 读取:

无符号整数类型具有相同的对象表示形式、值表示形式和对齐要求(6.7.6) 作为对应的有符号整数类型。对于有符号整数类型的每个值 x,值对应于 x 模 2 N 的无符号整数类型具有相同的对应位值其值表示。40 [示例:有符号整数类型的值 −1 具有与对应无符号类型的最大值。— 结束示例]

脚注40如下:

  1. 这也称为二的补码表示。

因此,C++现在要求有符号整数类型的二进制补码表示。

我猜你问的问题的答案是否定的。

我认为C++标准指定了最小大小,以及每个整数类型必须能够表示的值范围。我不认为该标准专门针对您列出的任何约束。

我认为这些都是实现细节。

我认为找到一个使用多个位来保存符号的C++实现会很奇怪,而不是使用 0 表示正数和 1 表示负数。但我不认为C++标准特别要求它。

C++ 标准特别基于 C 标准,其中写入了 (6.2.6.2 整数类型)

2 对于有符号整数类型,对象表示形式的位 应分为三组:值位、填充位和 符号位。不需要任何填充位;签名字符不得 有任何填充位。应该只有一个符号位.....

只有一个

符号位的要求意味着必须能够识别为所有负数设置的位,并清除所有非负数的位。 实现可以在"int"中包含任意数量的填充位,对其值施加任意限制,并将违反这些要求的任何位模式视为陷阱表示形式,前提是生成定义的整数值的所有计算都会生成实现将接受的位模式。

例如,实现可以将"int"存储为两个 16 位字,并指定第一个字的 MSB 是符号位。 这样的实现可以写入第一个单词的 0-14 匹配符号位和在读取任何不读取值时进行 trap,或使这些位与位匹配第二个单词的 1-15(同样陷印),或者可以写入任意值到这些位并在阅读时忽略它们,或者做任何其他事情和他们在一起。 如果实现总是将顶部单词写为所有单词或所有零,任何位都可以被指定为"符号位",这无关紧要;其余的都将是"填充位"。

只有一个符号位的要求将主要排除例如正数可以任意表示的实现作为位模式 00 或 11,负数为 01 或 10。 在这样的一个实现时,有必要检查两个位而不是一个位以确定数字是负数还是非负数。