在C语言中实现逻辑右移
我正在研究在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 <<
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);
}