【发布时间】:2013-11-08 22:54:15
【问题描述】:
如何在 C 中检测 int 符号?
这个问题主要是关于历史机器的。我要问的是如何区分整数是0还是-0。在 1 的补码和符号/幅度 int 编码中,0(或 +0)和 -0 都是可能的。
简单的符号位测试是与0比较。
int x;
printf("sign bit is %s\n", (x < 0) ? "set" : "not set");
但是当x 是-0 时,这在 1 的补码和符号幅度上会失败。
第一种候选方法:模板测试。
由于 C 定义 int 必须有一个符号位,无论整数编码如何,以下应该可以工作。
int x;
int SignBitMask = tbd;
printf("sign bit is %s\n", (x & SignBitMask) ? "set" : "not set");
问题变成了如何在 C 中确定SignBitMask 的值?SignBitMask = INT_MAX + 1 似乎是一个起点。
第二种候选方法:创建函数并检查位模式:
int IsSignBitSet(int x) {
if (x > 0) return 0;
if (x < 0) return 1;
int zp = 0;
if (memcmp(&x, &zp, sizeof x) == 0) return 0;
int zn = -0; // Is this even the way to form a -0?
if (memcmp(&x, &zn, sizeof x) == 0) return 1;
// If we get here, now what?
return ?;
}
我认为没有便携式统一解决方案 - 可能是因为不再需要。
为什么:我想知道如何检测和打印各种带符号的零。
注意:我在这里故意避开了“C”标签,并认为我会先尝试“历史”标签。
[编辑]答案
结合3个答案的信息和C11dr 6.2.6.2“整数类型”(对于int,单个符号位必须存在,正符号位为0,负符号位为1 ),一个解决方案(看起来独立于 1 的补码、2 的补码和符号/幅度整数编码)是
int IsSignBitSet_Best(int x) {
// return 1 if x is less than 0 _or_ x is arithmetically 0 with some bit set.
return (x < 0) || ((x == 0) && (* ((unsigned int*) &x) ));
}
直接掩码方法最简单,但还没有提出高度可移植的掩码定义
int IsSignBitSet_Simple(int x) {
static unsigned SignBitMask = 0x80; // Or some other platform dependent mask
return ((unsigned)x & SignBitMask) != 0;
}
【问题讨论】:
-
如果您只包含像history 这样的次要标签(甚至可能需要被烧掉),问题可能不会被很多人看到。
-
C 中的“符号位”是所有这些表示的第一位 (MSB)。 -0 被视为负数。
-
@Eric Postpischil 我对您的补充编辑表示赞赏。
标签: c history twos-complement