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

发布于 2024-11-01 10:51:47 字数 506 浏览 6 评论 0原文

新的 C++ 标准仍然拒绝指定整数类型的二进制表示。这是因为 C++ 的实际实现不使用 2 的补码算术吗?我觉得很难相信。是因为委员会担心未来硬件的进步会使“位”的概念过时吗?再次难以置信。任何人都可以阐明这一点吗?

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

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

其次,来自 James Kanze 的评论:

当赋值给 long 时,如果该值不适合 long,则结果为 实现定义

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

The new C++ standard still refuses to specify the binary representation of integer types. Is this because there are real-world implementations of C++ that don't use 2's complement arithmetic? 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 to this question). First, from piotr's comment:

Right shift on signed type is undefined behaviour

Second, from James Kanze's comment:

when assigning to a long, if the value doesn't fit in a long, the results are
implementation defined

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. WHY?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

岁吢 2024-11-08 10:51:47

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

  • ) ,编译器是在假设未定义的情况下构建的。更改标准不会改变编译器,而检查编译器以找出假设的位置是一项艰巨的任务。

  • 即使在 2 补码机器上,您的多样性也可能比您想象的要多。两个例子:有些没有保留右移的符号,只有引入零的右移; DSP 的一个共同特征是饱和算术,分配超出范围的值会将其限制在最大值,而不仅仅是丢弃高位。

(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.)

  • 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. 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.

把人绕傻吧 2024-11-08 10:51:47

我想这是因为标准在 3.9.1[basic.fundamental]/7 中说

此国际标准允许整数类型使用 2 的补码、1 的补码和带符号的大小表示。

我敢打赌,它来自 C 编程语言,其中列出了符号和幅度二的补码一个的补码6.2.6.2/2 中唯一允许的表示形式。当 C 广泛传播时,肯定存在 1 的补码系统:UNIVAC 似乎是最常被提及的。

I suppose it is because the Standard says, in 3.9.1[basic.fundamental]/7

this International Standard permits 2’s complement, 1’s complement and signed magnitude representations for integral types.

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. And there sure were 1's complement systems around when C was wide-spread: UNIVACs are the most often mentioned, it seems.

跨年 2024-11-08 10:51:47

在我看来,即使在今天,如果您正在编写一个广泛适用的 C++ 库并希望在任何机器上运行,那么就不能假设 2 的补码。 C++ 的使用太过广泛,无法做出这样的假设。

不过,大多数人不会编写此类库,因此如果您想依赖 2 的补码,您应该继续。

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++ is just too widely used to be making assumptions like that.

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.

澉约 2024-11-08 10:51:47

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

标准委员会尚未认为适合实施的解决方案是允许代码以独立于机器字长或硬件特性的方式指定事物所需的语义。如果认为对依赖于补码行为的代码的支持很重要,请设计一种方法,使代码可以明确要求补码行为,而不管底层硬件平台如何。如果需要,为了避免每个编译器过于复杂,请指定标准的某些方面是可选的,但符合标准的编译器必须记录它们支持哪些方面。这样的设计将允许补码机器的编译器根据程序的需要支持补码行为和补码行为。此外,它还可以将代码移植到二进制补码机器上,而编译器恰好包含补码支持。

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

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文