以下代码如何工作以及变量意味着什么:
y = (x << shift) | (x >> (sizeof(x)*CHAR_BIT - shift));
我在循环转换文章中找到了但没有解释它是如何工作的。
答案 0 :(得分:25)
这是一种循环移位的方法。假设x
是8位。
+----+----+----+----+----+----+----+----+ | x1 x2 x3 x4 x5 x6 x7 x8 | +----+----+----+----+----+----+----+----+
然后,将它向左移动3给我们:
+----+----+----+----+----+----+----+----+ | x4 x5 x6 x7 x8 0 0 0 | +----+----+----+----+----+----+----+----+
现在,CHAR_BIT*sizeof(x)
与位数x
的宽度相同,8。x
向右移动8 - 3
给了我们:
+----+----+----+----+----+----+----+----+ | 0 0 0 0 0 x1 x2 x3 | +----+----+----+----+----+----+----+----+
接受你的OR:
+----+----+----+----+----+----+----+----+ | x4 x5 x6 x7 x8 x1 x2 x3 | +----+----+----+----+----+----+----+----+
这在技术上是不可移动的,因为移动的数量等于类型的宽度是不可移动的 - 所以如果shift是8,那么左移是错误的,如果移位是0,那么正确的转变是错误的。但是,当按类型宽度移动时,这适用于所有三种常见行为。 (实际上,移位量会减少一些模数 - 或者是类型的位宽或更大的数字。)
它被称为循环移位或“旋转”,因为在左侧移出的位会向右移回。
复杂的编译器实际上会将代码编译为硬件循环指令。
答案 1 :(得分:18)
CHAR_BIT
是每个字节的位数,应始终为8。
shift
是您想要以循环方式向左移位的位数,因此向左移出的位返回右侧。
1110 0000 << 2 results in:
1000 0011
示例代码:
y = (x << 2) | (x >> (8 - 2));
答案 2 :(得分:4)
(x << shift)
向左移位“移位”位数,返回移出的位
(x >> (sizeof(x)*CHAR_BIT - shift));
为容纳这些位留出空间
CHAR_BIT
是char中的位数,因此主要是8位。
在C中,您不是一次处理一个位,而是至少处理char位数。这就是你得到的粒度。
一般来说,
对于char,当你进行位旋转时,你会在8位字段(1字节)上进行
对于int,当你进行旋转时,你可以在32位字段(4字节)上进行
8位示例:
x = 11010101
shift = 2
x << (2) = 01010100 //shifted right by 2 bits
= x >> ((1 * CHAR_BIT) - 2)
= x >> (6)
= 00000011 //shifted left by 6bits
OR
这些按位提供
01010101
00000011
________
01010111
这是循环移位值2位
答案 3 :(得分:0)
这仅适用于无符号类型。在带符号的负数的情况下,大多数左位将被右移运算符(“&gt;&gt;”)
替换为最高有效位(1-s)的值。我会这样写:
y = (x << shift) | ( (x >> (sizeof(x)*CHAR_BIT - shift)) & (0x7F >> (sizeof(x)*CHAR_BIT - shift) );
在此之前“|”运算符我们确认前n位(n = sizeof(x)* CHAR_BIT - 移位)归零。 我们还假设x很短(2个字节长)。所以,它也是类型依赖的。