在C语言中实现逻辑右移

在C语言中实现逻辑右移,c,bit-manipulation,C,Bit Manipulation,我正在研究在C语言中只使用位运算符生成逻辑右移函数。以下是我所拥有的: int logical_right_shift(int x, int n) { int size = sizeof(int); // size of int // arithmetic shifts to create logical shift, return 1 for true return (x >> n) & ~(((x >> (size <<

我正在研究在C语言中只使用位运算符生成逻辑右移函数。以下是我所拥有的:

int logical_right_shift(int x, int n)
{
    int size = sizeof(int); // size of int

    // arithmetic shifts to create logical shift, return 1 for true
    return (x >> n) & ~(((x >> (size << 3) - 1) << (size << 3) -1)) >> (n-1);
}
int逻辑向右移位(int x,int n)
{
int size=sizeof(int);//int的大小
//算术移位创建逻辑移位,返回1为真

返回(x>>n)和((x>>(大小只需将您的
int
存储在
无符号int
中,并对其执行
>

(如果使用unsigned int,则不会扩展或保留符号)


与@Ignacio的评论一样,我不知道您为什么要这样做(而不只是像其他答案中那样对
无符号的
进行转换),但是(假设2的补码和二进制,并且有符号的移位是算术的):


(x>>n)+(1n)^((INT\u MIN>>n)我想问题出在你的“>>(n-1)”部分。如果n为0,那么左边的部分将移位-1。
所以,这是我的解决方案

int logical_right_shift(int x, int n)
{
  int mask = ~(-1 << n) << (32 - n);
  return  ~mask & ( (x >> n) | mask); 
}
int逻辑向右移位(int x,int n)
{
int mask=~-1N | mask);
}
源于


仅适用于32位平台。

这是您需要的:

int逻辑向右移位(int x,int n)
{
int size=sizeof(int)*8;//通常sizeof(int)是4字节(32位)
返回(x>>n)&((0x1>n)>n
向右移位
n位
。但是,如果
x
为负,符号位(最左边的位)将被复制到其右侧,例如:

假设每个int都是32位,让
x     = -2147483648 (10000000 00000000 00000000)
,然后
x >> 1. = -1073741824 (110000000000000000000000000000)

x >> 2. = -536870912  (1110000000000000000000000000)

等等

因此,当n为负时,我们需要删除这些符号额外的符号位

假设
n=5

0x1 n)n)>n

(x >> n) & ~(((0x1 << size) >> n) << 1)

(x>>n)和((0x1>n)Milnex的答案很好,并且有一个非常棒的解释,但不幸的是,由于总大小的变化,实现失败了。下面是一个工作版本:

int logicalShift(int x, int n) {
  int totalBitsMinusOne = (sizeof(int) * 8) - 1; // usually sizeof(int) is 4 bytes (32 bits)
  return (x >> n) & ~(((0x1 << totalBitsMinusOne) >> n) << 1);
}
int逻辑移位(int x,int n){
int totalBitsMinusOne=(sizeof(int)*8)-1;//通常sizeof(int)是4字节(32位)
返回(x>>n)和((0x1>n)
int逻辑移位(int x,int n){
int mask=x>>31(n)n);
}

仅针对32位

您正在为有符号类型生成逻辑右移运算符?如果(n==0){return x;}
有什么问题?使用@Mark的建议,您可以将其更改为此(不保证它工作):
return(n==0?x:(x>>n)和((x>>(size@Dan:你想在答案中允许强制转换吗?应该在没有强制转换或条件语句的情况下进行。这是正确的答案(对结果中不必要和丑陋的强制转换进行模化)。负值的右移有实现定义的行为(或者是实现定义的值?我忘了)因此,在有符号值上使用
运算符的
lsr
函数的任何实现都是不可移植的。此解决方案的一个问题是:严格来说,在
n==0
的情况下,它具有实现定义的行为,因为从
int
转换为
无符号的
,并返回结果在实现定义的行为中,如果原始值为负值。第一次转换必须以模
UINT_MAX+1
进行,但转换回带符号的
int
可能只是对表示的重新解释,在这种情况下,值将被更改。@R..Hi,您能给出一个示例或代码片段来帮助请让我理解你的意思?谢谢。我认为这是正确的。但是你能做32次左移位吗?那将是一个未定义的移位吗?是的,如果
int
是,例如,4个字节,这将失败。他需要从
size
中减去1,这样如果
int
是4个字节,
size
是31。请为exp添加更多信息躺在你的答案上。只有代码的答案在这里不被广泛接受。@MarkYisri讽刺的是,在这个“线索”上,排名靠前的答案很明显,是代码唯一且完美地回答了这个问题。如果
x>>31
导致非零值,这将导致未定义的行为。这是一个优雅的解决方案,因为它不涉及条件语句,因此没有CPU分支。最终的
|mask
操作是不必要的,因为该OR操作设置为1的每一位都将被设置为to 0通过AND操作。掩码计算可以简化如下:
int mask=int.MinValue>>(n-1);
但是如果n==0,我的简化将产生不正确的结果,因此这取决于您的用例-这种简化不适用于库。
int logical_right_shift(int x, int n)
{
  int mask = ~(-1 << n) << (32 - n);
  return  ~mask & ( (x >> n) | mask); 
}
function logical_right_shift( i , shift ) {

    if( i & 2147483648 ) {
        return ( i >> shift ) ^ ( 2147483648 >> ( shift - 1 ) );
    }

    return i >> shift;
}
(x >> n) & ~(((0x1 << size) >> n) << 1)
int logicalShift(int x, int n) {
  int totalBitsMinusOne = (sizeof(int) * 8) - 1; // usually sizeof(int) is 4 bytes (32 bits)
  return (x >> n) & ~(((0x1 << totalBitsMinusOne) >> n) << 1);
}
int logicalShift(int x, int n) {
  int mask = x>>31<<31>>(n)<<1;
  return mask^(x>>n);
}