C:设置变量范围内所有位的最有效方法

标签 c bit-manipulation

我们以int为例举个例子:

int SetBitWithinRange(const unsigned from, const unsigned to)
{
    //To be implemented 
} 

SetBitWithinRange应该返回 int其中所有且只有从位 from 开始的位到位to被设置,当 from 是 smallerto两者都在 0 的范围内至 32 .

例如: int i = SetBitWithinRange(2,4)将导致 i值为 0b00...01100

最佳答案

这里有一些方法。首先,“设置 n 位,然后移位 from”的一些变体。不过我会用 C# 回答,我对它比对 C 更熟悉。应该很容易转换。

uint nbits = 0xFFFFFFFFu >> -(to - from);
return nbits << from;

缺点:无法处理空范围,即 to <= from 的情况.

uint nbits = ~(0xFFFFFFFFu << (to - from));
return nbits << from;

优点:可以处理 to = from 的情况在这种情况下,它不会设置任何位。
缺点:无法处理整个范围,即设置所有位。

这些是如何工作的应该很明显。

或者,您可以使用“减去 2 的二次方”技巧,

(1u << to) - (1u << from)

缺点:to不能是 32,所以你永远不能设置最高位。

像这样工作:

01000000
  ^^^^^^ "to" zeroes
     100
      ^^ "from zeroes"
-------- -
00111100

在“from”部分中 1 的右侧,它只是从零中减去零。然后在“从”部分的 1 处,您将从 1 中减去(如果 to == from )并得到 0 作为结果,或者您将从 0 中减去 1 并一直借到 1 to部分,这将被重置。

在撰写本文时提出的所有真正的按位方法都有其中一个缺点,这就提出了一个问题:它可以在没有缺点的情况下完成吗?

不幸的是,答案令人失望。它可以在没有缺点的情况下完成,但只能通过

  1. 作弊(即使用非按位元素),或
  2. 更多的操作,或者
  3. 非标准操作

以 1 为例,您可以选择前面的任何方法并添加一个特殊情况(使用 if 或三元运算符)来解决它们的缺点。

举个例子2:(未测试)

uint uppermask = (((uint)to >> 5) ^ 1) << to;
return uppermask - (1u << from);

uppermask取 1 并将其左移 to (像往常一样),或者如果 to == 32,它需要一个 0 并将其左移(移动一个无关紧要的量,因为它被移动的是 0)。 .但它有点奇怪并且使用了更多的操作。

举个 3 的例子,当你移位操作数大小或更多时给出零的移位会很容易地解决这个问题。不幸的是,这种转变并不常见。

关于C:设置变量范围内所有位的最有效方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22662807/

相关文章:

c - 汇编语言是如何工作的?

C编程中的编译器错误 "void value not ignored as it ought to be"

c - 在 unsigned int 中搜索位模式

bit-manipulation - Elixir 中的左旋转按位运算/为什么缺少带符号的左移?

Java打印整数与Integer.toHexString() : Different outputs

c - 调用 make 时缺少分隔符

c - 如何为 TMS320F2812 DSP 编写内存屏障?

java - 将函数指针的 C 结构体转换为 JNA 代码

c - C : Checking if a number is positive 中的按位运算

java - Java中无符号右移运算符 ">>>"的目的是什么?