Это то, что вам нужно:
int logical_right_shift(int x, int n)
{
int size = sizeof(int) * 8; // usually sizeof(int) is 4 bytes (32 bits)
return (x >> n) & ~(((0x1 << size) >> n) << 1);
}
Объяснять
x >> n
сдвиги n bits
вправо. Однако, если x
отрицательно, бит знака (крайний левый бит) будет скопирован вправо, например:
Предположим, что каждое int 32 бита здесь, пусть
x = -2147483648 (10000000 00000000 00000000 00000000)
, затем
x >> 1 = -1073741824 (11000000 00000000 00000000 00000000)
x >> 2 = -536870912 (11100000 00000000 00000000 00000000)
и т. д.
Так что нам нужно стереть эти знаковые дополнительные знаковые биты, когда n отрицательно.
Предположим n = 5
здесь:
0x1 << size
перемещается 1
в крайнее левое положение:
(10000000 00000000 00000000 00000000)
((0x1 << size) >> n) << 1
копирует 1 своим n-1
соседям:
(11111000 00000000 00000000 00000000)
~((0x1 << size) >> n) << 1!
инвертирует все биты:
(00000111 11111111 11111111 11111111)
так что мы наконец-то получили маску для извлечения того, что действительно нужно из x >> n
:
(x >> n) & ~(((0x1 << size) >> n) << 1)
операция &
делает свое дело.
А общая стоимость этой функции составляет 6
операций.