如何检测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;
}
答案 0 :(得分:2)
要找到负0,只需检查所有设置为任意位的零。
int testForNegative0(int x) {
return (x==0 && *((unsigned int*)&x));
}
或者回答标题中的问题:
int hasSignBitSet(int x) {
return (x<0) || testForNegative0(x);
}
这适用于你提到的3种编码,它可能不适用于更深奥的编码。
答案 1 :(得分:1)
不确定你究竟在问什么。如果你问'我们如何确定一台机器是补码,二补码还是符号幅度?'你可以使用:
if (1 & -1) {
if (3 & -1 == 1)
printf("sign magnitude\n");
else
printf("twos complement\n");
} else
printf("ones complement\n");
答案 2 :(得分:1)
你的问题有点令人困惑。你提前知道编码吗?如果不是,那么你所要求的是不可能的,因为不同编码的映射是不同的。例如,字节1111111
在一个补码中具有0的“符号”,但在二进制补码中具有-1的符号。那么如何才能有一种通用的方法来检查它们的定义是否不同?
int sign(int x)
{
if (x > 0) return 1;
if (x > -1) return 0;
return -1;
}