【问题标题】:How to find the most significant bit of a signed integer in C如何在C中找到有符号整数的最高有效位
【发布时间】:2021-02-28 22:02:31
【问题描述】:

我需要找到signed int N 的最高位并将其保存在signBitN 中。我想使用仅按位操作来做到这一点。 另外,我将如何使 signBitN 扩展以使其所有位都等于其有效位。 即如果它的有效位为零,我将如何将其扩展为 00000...00? 我得到的最接近的是 signBitN=1&(N>>(sizeof(int)-1));

【问题讨论】:

  • 什么是 N?是否要查找特定类型的符号位,例如 intint16_t
  • 换档(CHAR_BIT*sizeof(int)-1)
  • 与明显的(N < 0)(N < 0) ? -1 : 0 相比,使用位运算符执行此操作并没有特别的好处。如果有聪明的按位方法,让编译器的优化器为您插入它们。 Example.
  • N 是有符号整数
  • 你是在问什么是最高位,还是要找到第一个1

标签: c bit-manipulation bitwise-operators bit-shift bitwise-and


【解决方案1】:

便携表达:

1 & (x >> (CHAR_BIT * sizeof(int) - 1))

最新的 C 标准对 int 的表示提出了 3 个标准。

  • 符号和大小
  • 补码
  • 二补 请参阅 C11 标准的 6.2.6.2 Integer types 部分。

只有第三个选项在实践中与现代机器相关。 如6.2.6.1中所述:

存储在任何其他对象类型的非位域对象中的值 由 n x CHAR_BIT 位组成,其中 n 是该类型对象的大小, 以字节为单位。

因此int 将由sizeof(int) * CHAR_BIT 位组成,可能是 32。 因此,int 的最高位可以通过右移sizeof(int) * CHAR_BIT - 1 位并使用按位& 运算符读取最后一位来读取。

请注意,移位后int 的确切值是如6.5.7.5 中所述的实现定义。

在正常的机器上是这样的:

int y = x < 0 ? -1 : 0;

可移植的方式是在intunsigned char 的数组之间进行转换,并将所有字节设置为-1。 见6.3.1.3.2:

如果新类型是无符号的,则值转换为 重复加或减一大于最大值 可以在新类型中表示的值,直到值 在新类型的范围内。

还有6.2.6.1.2

存储在无符号位域和类型对象中的值 unsigned char 应使用纯二进制表示法表示。

你可以使用memset()

int x;
memset(&x, (x < 0 ? -1 : 0), sizeof x);

【讨论】:

  • 如果x 为负数,则x &gt;&gt; 具有实现定义的结果。例如,某些实现可能会填充零位。
  • @M.M,是的,它的实现已定义。但问题是关于最高位的值之前移动
  • 整个结果是实现定义的;该标准不保证您的第一个建议会给出正确的答案。因此,也许“可移植”并不是对该代码的良好描述。
  • @MM 是的。操作的结果是实现定义的,因为“int”的位表示是实现定义的。也许首先应该定义最高位的概念。
  • @tstanisl 那么如果 t 不可移植,为什么还要使用它呢?
【解决方案2】:

如果问题是如何检查整数的 MSB 位(例如 32 位整数的第 31 位)十 IMO,这是可移植的。

#define MSB(i)   ((i) & (((~0U) >> 1) ^ (~0U)))
#define issetMSB(i) (!!MSB(i))

int main(void)
{
    printf("%x\n", MSB(-1));
    printf("%x\n", issetMSB(-1));
}

【讨论】:

  • ...如果“强制转换为无符号”是允许的操作之一(从 OP 中不清楚)
  • @M.M 是不允许的,那么在便携式 C 中是不可能的。
  • @M.M 不需要加入
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-07-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多