简体   繁体   English

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

[英]Why not enforce 2's complement in C++?

The new C++ standard still refuses to specify the binary representation of integer types.新的 C++ 标准仍然拒绝指定整数类型的二进制表示。 Is this because there are real-world implementations of C++ that don't use 2's complement arithmetic?这是因为 C++ 的实际实现不使用 2 的补码算法吗? I find that hard to believe.我觉得很难相信。 Is it because the committee feared that future advances in hardware would render the notion of 'bit' obsolete?是因为委员会担心未来硬件的进步会使“位”的概念过时吗? Again hard to believe.再次难以置信。 Can anyone shed any light on this?任何人都可以对此有所了解吗?

Background: I was surprised twice in one comment thread (Benjamin Lindley's answer tothis question ).背景:我在一个评论线程中两次感到惊讶(Benjamin Lindley 对这个问题的回答)。 First, from piotr's comment:首先,来自 piotr 的评论:

Right shift on signed type is undefined behaviour有符号类型的右移是未定义的行为

Second, from James Kanze's comment:其次,来自 James Kanze 的评论:

when assigning to a long, if the value doesn't fit in a long, the results are implementation defined分配给 long 时,如果该值不适合 long,则结果是实现定义的

I had to look these up in the standard before I believed them.在我相信它们之前,我必须在标准中查找这些。 The only reason for them is to accommodate non-2's-complement integer representations.它们的唯一原因是适应非 2 的补整数表示。 WHY?为什么?

(Edit: C++20 now imposes 2's complement representation, note that overflow of signed arithmetic is still undefined and shifts continue to have undefined and implementation defined behaviors in some cases.) (编辑:C++20 现在强加 2 的补码表示,请注意有符号算术的溢出仍然未定义,并且在某些情况下,移位继续具有未定义和实现定义的行为。)

  • A major problem in defining something which isn't, is that compilers were built assuming that is undefined.定义一些不是的一个主要问题是编译器是在假设未定义的情况下构建的。 Changing the standard won't change the compilers and reviewing those to find out where the assumption was made is a difficult task.改变标准不会改变编译器,检查那些以找出假设的地方是一项艰巨的任务。

  • Even on 2 complement machine, you may have more variety than you think.即使在 2 补充机上,您的多样性也可能比您想象的要多。 Two examples: some don't have a sign preserving right shift, just a right shift which introduce zeros;两个例子:有些没有保留右移的符号,只是一个引入零的右移; a common feature in DSP is saturating arithmetic, there assigning an out of range value will clip it at the maximum, not just drop the high order bits. DSP 中的一个共同特征是饱和算法,分配一个超出范围的值会将其剪裁到最大值,而不仅仅是丢弃高位。

I suppose it is because the Standard says, in 3.9.1[basic.fundamental]/7我想这是因为标准说,在3.9.1[basic.fundamental]/7

this International Standard permits 2's complement, 1's complement and signed magnitude representations for integral types.本国际标准允许整数类型的 2 的补码、1 的补码和带符号的幅度表示。

which, I am willing to bet, came along from the C programming language, which lists sign and magnitude , two's complement , and one's complement as the only allowed representations in 6.2.6.2/2 .我敢打赌,它来自 C 编程语言,它列出了符号和大小二进制补码补码作为6.2.6.2/2唯一允许的表示6.2.6.2/2 And there sure were 1's complement systems around when C was wide-spread: UNIVACs are the most often mentioned, it seems.当 C 广泛传播时,肯定有 1 的补码系统:似乎 UNIVAC 是最常被提及的。

It seems to me that, even today, if you are writing a broadly-applicable C++ library that you expect to run on any machine, then 2's complement cannot be assumed.在我看来,即使在今天,如果您正在编写希望在任何机器上运行的广泛适用的 C++ 库,则不能假设 2 的补码。 C++ is just too widely used to be making assumptions like that. C++ 被广泛用于做出这样的假设。

Most people don't write those sorts of libraries, though, so if you want to take a dependency on 2's complement you should just go ahead.但是,大多数人不会编写这类库,因此如果您想依赖 2 的补码,则应该继续。

Many aspects of the language standard are as they are because the Standards Committee has been extremely loath to forbid compilers from behaving in ways that existing code may rely upon.语言标准的许多方面都是如此,因为标准委员会非常不愿意禁止编译器以现有代码可能依赖的方式行事。 If code exists which would rely upon one's complement behavior, then requiring that compilers behave as though the underlying hardware uses two's complement would make it impossible for the older code to run using newer compilers.如果存在依赖于补码行为的代码,那么要求编译器的行为就像底层硬件使用二进制补码一样,将使旧代码无法使用新编译器运行。

The solution, which the Standards Committee has alas not yet seen fit to implement, would be to allow code to specify the desired semantics for things in a fashion independent of the machine's word size or hardware characteristics.标准委员会认为该解决方案尚不适合实施,它是允许代码以独立于机器字长或硬件特性的方式为事物指定所需的语义。 If support for code which relies upon ones'-complement behavior is deemed important, design a means by which code could expressly demand one's-complement behavior regardless of the underlying hardware platform.如果认为对依赖于补码行为的代码的支持很重要,请设计一种方法,使代码可以明确要求自己的补码行为,而不管底层硬件平台如何。 If desired, to avoid overly complicating every single compiler, specify that certain aspects of the standard are optional, but conforming compilers must document which aspects they support.如果需要,为了避免使每个编译器过于复杂,请指定标准的某些方面是可选的,但符合标准的编译器必须记录它们支持哪些方面。 Such a design would allow compilers for ones'-complement machines to support both two's-complement behavior and ones'-complement behavior depending upon the needs of the program.这种设计将允许二进制补码机器的编译器根据程序的需要支持二进制补码行为和个人补码行为。 Further, it would make it possible to port the code to two's-complement machines with compilers that happened to include ones'-complement support.此外,它可以将代码移植到二进制补码机器,编译器恰好包含一个补码支持。

I'm not sure exactly why the Standards Committee has as yet not allowed any way by which code can specify behavior in a fashion independent of the underlying architecture and word size (so that code wouldn't have some machines use signed semantics for comparisons where other machines would use unsigned semantics), but for whatever reason they have yet to do so.我不确定为什么标准委员会还不允许代码以独立于底层架构和字长的方式指定行为(这样代码不会让某些机器使用签名语义进行比较,其中其他机器将使用无符号语义),但无论出于何种原因,他们还没有这样做。 Support for ones'-complement representation is but a part of that.对ones'-complement 表示的支持只是其中的一部分。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM