【问题标题】:What does the following mean wrt. binary representations of signed types in C language?以下是什么意思。 C语言中带符号类型的二进制表示?
【发布时间】:2022-01-18 13:18:03
【问题描述】:

C 允许三种不同的符号表示:

  • 符号和大小

  • 反码

  • 补码

前两个现在可能只具有历史或异国情调:对于符号和幅度,幅度被视为正值,符号位只是指定有一个减号。反码取相应的正值, 补全所有位。 这两种表示都有一个缺点,即两个值的计算结果为 0:有一个正 0 和一个负 0。

来源:Modern C,Jens Gustedt

问题:根据最后一条语句(粗体),“两个值计算为零”有什么问题?

【问题讨论】:

  • 对于有符号整数(以及浮点数),最左边的位保留给符号位。所以,1000......0000 和 0000......0000 都为零,但前者的符号位打开,意思是“负数”。
  • 一个 8 位整数有 256 个可能的数字。如果你有两个数字,你只有 255 个可能的数字。例如,-128 到 127 用于 2s 补码,-127 到 127 用于另一个。
  • 怎么了……?好吧,除了您“浪费”一种可能的表示(微不足道)这一事实之外,如果两个零值具有不同的表示,代码可能会在位比较中失败。
  • 或许问@Jens Gustedt?
  • @AdrianMole you're 'wasting' one possible representation 参数也适用于常见的浮点。 -INT_MAX != INT_MIN 也有 2 的补码问题。我不认为非 2 的补码是错误的,因为多年来它输给了 2 的补码作为较弱的方法。

标签: c signed


【解决方案1】:

根据最后一条语句(粗体),“两个值计算为零”有什么问题?

示例:字符串

当char被签名时,如果整数编码不是2的补码,这段代码有什么问题?

size_t my_strlen(const char *s) {
  const char *t = s;
  while (*t) {
    t++;
  }
  return t - s;
} 

while (*t) 在 +0 和 -0 上都停止,而它应该只在 +0 上停止。

字符串处理<string.h> 对于本小节中的所有函数,每个字符都应被解释为具有unsigned char 类型(因此每个可能的对象表示都是有效的并且具有不同的值)。 C17dr 7.24.1 3

应该使用const unsigned char *t = s;。使用 2 的补码,无论哪种方式都没有区别。

基本问题是有时代码应该区分 +0 和 -0,但普通代码只看 value,而不是 signed 的符号为0时为整数。


C2x 预计需要 2 的补码。

非2补码的角好处:对称正负范围。 所有i 的abs(i) 值。 -i 对所有 i 有效。 -1/x 对于非零 x 来说从来都不是问题。

【讨论】:

  • 请注意,示例代码可能是人为的,但仅用于说明。我希望 char 是 unsigned 具有罕见的非 2 补码实现。
  • 请注意,二进制浮点通过 sign-magnitude 有效地编码符号和显着性。
猜你喜欢
  • 1970-01-01
  • 2020-06-29
  • 2014-05-22
  • 2015-05-09
  • 2021-03-29
  • 1970-01-01
  • 2022-01-08
  • 2022-01-05
  • 2011-01-14
相关资源
最近更新 更多