如何在C语言中检测有符号整数的编码?

15

ISO C标准允许使用三种编码方法来表示带符号的整数:补码、反码和原码。

有什么有效或好的方法可以在运行时(或其他时间,如果有更好的解决方案)检测编码呢?我想知道这个信息,以便为不同的可能性优化大数库。

我计划在程序每次运行时计算并将其存储在一个变量中,因此它不必非常快 - 我假设编码不会在程序运行期间改变 :-)


5
在特定架构的编译过程中,你永远不需要在运行时执行此操作,这纯粹是一个编译时问题。 - Paul R
2
对于大数库,你几乎总是需要无符号类型。虽然你可能能够使用有符号类型来表示最高位字,但更简单的方法是存储一个单独的符号位,并始终使用正数进行计算,然后根据符号位翻转加法/减法的意义。基本上就是你自己的符号/幅度表示法。 - R.. GitHub STOP HELPING ICE
5个回答

17
您只需使用类似于 -1&3 的内容检查常量 -1 的低位即可。
这将评估:
  1. 对于符号大小(Sign and Magnitude)
  2. 对于反码(One's Complement)
  3. 对于补码(Two's Complement)
这甚至应该可以在#if #else构造内的预处理器表达式中完成。

@Jens Gustedt的回答非常好!但是在交叉编译期间,到底检查了什么,编译器(预处理器)的编码还是目标机器的编码? - user2596047
1
@user2596047,编译器必须始终将所有表达式评估为在运行时评估的方式,以便生成的代码的执行与所谓的“抽象状态机”中的行为相同。因此,是的,即使是用于交叉编译,这也必须在目标机器的算术中完成,而不是在主机机器上完成。 - Jens Gustedt

12
检测一的补码应该很简单 - 类似于if (-x == ~x)。检测二的补码也应该非常容易: if (-x == ~x + 1)。如果不是这两种情况,那么它必须是符号/大小格式。

5
这些也是常量表达式,因此您可以在 #if 测试中使用它们:#define TWOSCOMPLEMENT(〜-1 == 0),然后 #if TWOSCOMPLEMENT - caf
3
你的表达并不一定适用于所有情况下的 x,所以在边界情况下需要小心。特别是对于二进制补码中的一个恶劣情况,即 -x 可能会导致未定义的行为,例如 -INT_MIN 可能会超出范围。 - Jens Gustedt

2

为什么不在编译时就做呢?如果需要,您可以让构建脚本/Makefile编译测试程序,然后使用预处理器进行条件编译。这也意味着性能大大不那么重要,因为它只运行一次每次编译,而不是每次运行。


0

获得一个指向显示不同位模式的int的指针。将其强制转换为无符号int类型的指针,然后检查位值。

选择一些特定的值进行操作应该可以实现你想要的效果。


-1

我猜你可以将一个负数存储为一个int,然后将其存储到足够大的char数组中,并将该数组与各种表示进行比较以找出结果。

但是,呃...无符号整数不应该有符号,对吧?


是的...看来我想得太复杂了...Jerry关于使用位运算进行检查是正确的。不用在意了。将其作为备选答案留在这里。 - Arc
是的,抱歉,那应该被签名。 - paxdiablo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接