C 仅使用逐位运算符创建标记最高有效设置位的掩码

C 仅使用逐位运算符创建标记最高有效设置位的掩码,c,bit-manipulation,C,Bit Manipulation,这是昨晚我要完成的一个更大的编程任务的一部分。我想不出这个问题,但我很好奇如何解决它 函数int greatestBitPos(int x)应返回标记最高有效位位置的int掩码。如果x==0,则返回0。不允许使用控制结构(如果、而、?:) 示例:greatestBitPos(96)=0x40 合法经营者:!~&^ |+>= 是我用来作为起点的,尤其是第二个算法。但是,它使用更新后的来处理负数(假设这应该返回0x8000000,因为这些数字的顶部位已设置) 说明: 从任何位模式开始,当我们右移1并

这是昨晚我要完成的一个更大的编程任务的一部分。我想不出这个问题,但我很好奇如何解决它

函数
int greatestBitPos(int x)
应返回标记最高有效位位置的int掩码。如果x==0,则返回0。不允许使用控制结构(如果、而、?:)

示例:
greatestBitPos(96)=0x40

合法经营者:!~&^ |+>=


是我用来作为起点的,尤其是第二个算法。但是,它使用更新后的
来处理负数(假设这应该返回
0x8000000
,因为这些数字的顶部位已设置)

说明:

从任何位模式开始,当我们右移1并取OR时,相邻位将变为1。范例

00010100
00001010
--------
00011110
通过连续移动2、4、8、16(如果您有32位数字;对于较大的
int
,则继续),重复此操作直到所有数字都位于前导数字的右侧

最后,您需要通过反转数字,右移1,然后取and,来“去除所有其他数字”:

00011111 AND 11110000 = 00010000
就在这里


对于负数,最后的操作确保不会杀死顶部位(如果它存在)。如果您想用负数做其他事情,请告诉我它是什么。

通过移位和/或将所有位填入最重要位的右侧:

0b 0010 0000 0000 0000 0100 0000 0000 0000
0b 0011 0000 0000 0000 0110 0000 0000 0000
0b 0011 1100 0000 0000 0111 1000 0000 0000
0b 0011 1111 1100 0000 0111 1111 1000 0000
0b 0011 1111 1111 1111 1111 1111 1111 1111
然后右移并添加1以保留最重要的一个:

0b 0001 1111 1111 1111 1111 1111 1111 1111
0b 0010 0000 0000 0000 0000 0000 0000 0000
代码:


我仍然很想看看其他人能想出什么,但是一个朋友已经找到了答案

int greatestBitPos(int x) {
  int a = x | (x >> 1);
  a = a | (a >> 2);
  a = a | (a >> 4);
  a = a | (a >> 8);
  a = a | (a >> 16);
  return ((a ^ (a >> 1)) | 0x80 << 24) & a;
}
int greatestBitPos(int x){
int a=x |(x>>1);
a=a |(a>>2);
a=a |(a>>4);
a=a |(a>>8);
a=a |(a>>16);

return((a^(a>>1))| 0x80事实上,您可以使用此处提到的第二种算法,只需稍加修改:

b
为0n1m形式的特殊情况下


保留。

分配一个_反转={SergeyL:很遗憾你删除了你的答案。你可以写
+~0
而不是
-1
,并说“这假设2的补码”.Two的补码假设是正确的。我会编辑这个问题。@H2CO3不是我删除它的原因。它返回了除最低有效集以外的所有位。@SergeyL.Ah好的。那么让我们再想想,好吗。我们是否允许赋值运算符
=
?并假设int的大小是预先知道的?(
32
位?)还有
|=
&=
运算符。非常优雅,我喜欢。@H2CO3-是的,这可能会稍微收紧一点。不确定这会对执行时间有多大影响。在这种情况下,我更喜欢清晰而不是密度-不过这是个人的事情。@Floris我理解。我只是想澄清一下:我没有尝试过o过早地优化代码。这完全不会影响执行时间。我几乎总是喜欢可读性而不是“效率”(我无法表达我多么讨厌这个词).就我个人而言,我可以更容易地阅读复合运算符,但如果你喜欢写出来,那没关系,我接受。@Floris,这个解决方案对负整数不起作用。我非常喜欢这个想法。但是,这个问题不允许使用
*
!=
运算符。我喜欢
右移加1
只得到一个MSB。比我的解决方案更优雅。
int greatestBitPos(int x) {
  int is_nonzero = (x != 0);
  x = x | (x >> 1);
  x = x | (x >> 2);
  x = x | (x >> 4);
  x = x | (x >> 18);
  x = x | (x >> 16);
  return (is_nonzero * ((x >> 1) + 1));
}
int greatestBitPos(int x) {
  int a = x | (x >> 1);
  a = a | (a >> 2);
  a = a | (a >> 4);
  a = a | (a >> 8);
  a = a | (a >> 16);
  return ((a ^ (a >> 1)) | 0x80 << 24) & a;
}
(a > b) == !!(a & ~b)
assign a_reversed = {<<{a}};
assign a_2s_compl = (~a_reversed) + 1'b1;
assign a_lsb_set  = a_reversed & a_2s_compl;
assign a_msb_set  = {<<{a_lsb_set}};