C中的移位操作

时间:2015-05-21 08:13:09

标签: c bit-manipulation bit-shift

是否可以转换0,因为您可以在C中转换操作时转换1

像这样的东西

for (i=0; i<32; i++) {
    if (data & 0x01) { 
        data |= (1<<i);
    }
    else { 
        data &=~ (0<<i);
    }
}

我正在检查某些位是否已设置,并且根据我在新变量中存储0 s或1 s,将每一位向左移位。

4 个答案:

答案 0 :(得分:3)

您不会移动01,您可以移位位值,无论是0还是1。换句话说,无论存储在中的,都可以移动位位置

C11标准,章节§6.5.7。 ,按位移位运算符

  

E1 << E2的结果是E1左移E2位位置;腾出的位用零填充。

就像那样,在1 s的情况下,移动可见

也就是说,< 是一个位移运算符(如代码中所示),<<是。

答案 1 :(得分:2)

<<(不是<!)不会移位一位。它改变了整数。当你说1<<5时,它会向左移动0000000000000001五个位置(给定一个16位值),这会给出00000000001000000<<5正在移动0000000000000000五个位置,这会产生0000000000000000(即相同的值)。其他位不是不确定的:你不能移动一个位(我假设你想要??????????1???????????????0?????之类的东西,但是数字不会像那样工作。)

这看起来像是典型的XY问题。您可能希望使用data来打开或关闭其他内容?询问那个。 (编辑:正如Joachim Pileborg在评论中所说的那样。)

答案 2 :(得分:1)

好消息是 - 你过度思考它。

取整数,说:01011011

将其左移1:10110110

整个事情&#39;一起转移;零被移入LSB。在右移的情况下,对于无符号或对已签名数字的实现定义,它再次为零:

  

E1&gt;的结果&gt; E2是E1右移E2位位置。如果E1具有无符号类型或者E1具有带符号类型和非负值,则结果的值是E1 / 2E2的商的整数部分。如果E1具有有符号类型和负值,则结果值是实现定义的。

S6.5.7

这意味着右移有符号数可能会导致算术移位或逻辑移位。

如果你想将1转移到低端,而不是0 s,只需用一个位掩码来表示你转移的位数。

答案 3 :(得分:0)

使用CPU寄存器执行移位操作。寄存器由许多位组成(8,16和32是常见的,你似乎有32个CPU),它们的组合可以解释为十进制值。

在您的示例中,您使用值1.C语言允许以多种方式表示值1,所有这些都会导致CPU寄存器的相同内容:

decimal      hexadecimal  binary
1            0x00000001   0b00000000000000000000000000000001
3713883835   0xDD5D5EBB   0b11011101010111010101111010111011

(在所有情况下,可以省略前导0。)

在二进制表示中,指定了所有CPU寄存器位值。如您所见,这包括0和1。因此,当您将值1置于寄存器中并使用<<运算符执行左移时,整个寄存器的内容将向左移位一位,并将0置于最低有效位。

在您的代码中,分配给数据的值将遵循以下模式:

i = 0,  data = 0x00000000000000000000000000000001
i = 1,  data = 0x00000000000000000000000000000010
i = 2,  data = 0x00000000000000000000000000000100
etc.
i = 30, data = 0x01000000000000000000000000000000
i = 31, data = 0x10000000000000000000000000000000

如果您要使用不同于1的值来移动,您当然会以不同的模式结束,但它会遵循相同的规则。即无论是否保持1或0,所有位都会移位。

for(i=0;i<32;i++)
{
    data = (165 << i) // 165 = 0xA5 = 0b10100101
}

Produces:
i = 0,  data = 0x00000000000000000000000010100101
i = 1,  data = 0x00000000000000000000000101001010
i = 2,  data = 0x00000000000000000000001010010100
etc.
i = 28, data = 0x10100000000000000000000000000000
i = 29, data = 0x01000000000000000000000000000000
i = 30, data = 0x10000000000000000000000000000000
i = 31, data = 0x00000000000000000000000000000000

注意当最高有效位移出寄存器时,模式会如何消失。

使用>>运算符执行右移的规则相同,只是位从最重要位移到最小位。

(有些CPU也有旋转和其他精彩的位操作指令。)