c - 如何在各种编码中统一检测整数的符号位(1's complement, 2' 的补码,符号大小)?

标签 c history twos-complement

如何检测 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”标签,并认为我应该先尝试“History”标签。


[编辑]答案

结合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,只需检查任意位是否设置为 0。

int testForNegative0(int x) { 
   return (x==0 && *((unsigned int*)&x)); 
}

或者回答标题中的问题:

int hasSignBitSet(int x) { 
   return (x<0) || testForNegative0(x);
}

这适用于您提到的 3 种编码,但可能不适用于更深奥的编码。

关于c - 如何在各种编码中统一检测整数的符号位(1's complement, 2' 的补码,符号大小)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19869976/

相关文章:

c++ - 对逗号在 C/C++ 中的工作方式有些困惑

c++ - 这是 ->> 一个旧的运算符还是一个错字/错误?

git - 为什么 git log 不显示移动文件的历史记录,我该怎么办?

binary - 2的补码错误

c++ - 找到一个 m*m (2<=m<n) 且总和最大的子数组;从 n*n int 数组中(有 +ve、-ve、0)

c - 如何访问二维数组的外边界元素?

c - 为什么这个进程不再处理 S​​IGUSR1?

git - 如何删除所有提交都被推送到错误存储库的分支?

x86-64 - 为什么 1 的补码仍然用于编码向量指令?

twos-complement - 如何从一个补码转换为二进制补码