为什么不在C++中强制执行 2 的补码?

Why not enforce 2's complement in C++?

本文关键字:补码 强制执行 C++ 为什么不      更新时间:2023-10-16

新的c++标准仍然拒绝指定整数类型的二进制表示。这是因为在现实世界中存在不使用2的补码算法的c++实现吗?我觉得这很难相信。是因为委员会担心未来硬件的发展会使"比特"这个概念过时吗?再一次难以置信。有人能解释一下吗?

背景:我在一个评论线程中两次感到惊讶(Benjamin Lindley对这个问题的回答)。首先,来自piotr的评论:

有符号类型的右移是未定义的行为

第二,摘自James Kanze的评论:

赋值给long类型时,如果值不适合long类型,则结果不适合实现定义的

在我相信它们之前,我必须在标准中查找它们。使用它们的唯一原因是为了适应非2补的整数表示。为什么?

(编辑:c++ 20现在强制使用2的补码表示,注意有符号算术的溢出仍然未定义,并且在某些情况下移位仍然具有未定义和实现定义的行为。)

  • 定义不存在的东西的一个主要问题是编译器是在假设未定义的情况下构建的。改变标准不会改变编译器,检查这些编译器以找出假设是在哪里做出的是一项艰巨的任务。

  • 即使在2补体机上,你也可能有比你想象的更多的变化。两个例子,有些没有保留符号的右移,只是右移引入了零;DSP的一个共同特点是饱和算法,在那里分配一个超出范围的值会将其剪切到最大值,而不仅仅是降低高阶位。

我想这是因为标准规定,在3.9.1[basic.fundamental]/7

对于整型,本国际标准允许2的补码、1的补码和有符号的量表示。

,我敢打赌,来自C编程语言,它列出了符号和大小 2的补 1的补作为6.2.6.2/2中唯一允许的表示。当C广泛传播时,肯定有1的补充系统:univac似乎是最常被提到的。

在我看来,即使在今天,如果你正在编写一个广泛适用的c++库,并且你希望在任何机器上运行,那么2的补充不能被假设。c++的使用太广泛了,不能做这样的假设。

大多数人不会写这种类型的库,所以如果你想依赖于2的补充,你应该继续。

语言标准的许多方面都是这样的,因为标准委员会极不愿意禁止编译器以现有代码可能依赖的方式运行。如果存在依赖于一个补码行为的代码,那么要求编译器的行为就像底层硬件使用两个补码一样,将使旧代码无法使用新编译器运行。

标准委员会还没有看到合适的解决方案,允许代码以一种独立于机器字长或硬件特性的方式指定事物所需的语义。如果对依赖于补码行为的代码的支持被认为是重要的,那么设计一种方法,通过这种方法,无论底层硬件平台如何,代码都可以明确地要求补码行为。如果需要,为了避免使每个单独的编译器过于复杂,可以指定标准的某些方面是可选的,但是符合标准的编译器必须记录它们支持哪些方面。这样的设计将允许1补码机器的编译器根据程序的需要同时支持2补码行为和1补码行为。此外,它还可以将代码移植到具有恰好包含1补码支持的编译器的两台补码机器上。

我不确定为什么标准委员会还不允许代码以独立于底层架构和字长的方式指定行为(这样代码就不会让一些机器使用带符号语义进行比较,而其他机器使用无符号语义),但无论出于什么原因,他们还没有这样做。对ones的补码表示的支持只是其中的一部分。