C 中的移位操作
Shift operation in C
是否可以像在 C 中的移位操作中移位 1
s 那样移位 0
s?
像这样
for (i=0; i<32; i++) {
if (data & 0x01) {
data |= (1<<i);
}
else {
data &=~ (0<<i);
}
}
我正在检查是否设置了某些位,并根据这些设置将 0
s 或 1
s 存储在新变量中,将每一位向左移动。
您不移动 0
或 1
,而是移动位值,无论是 0
还是 1
。换句话说,您移动 位位置 ,而不管其中存储的 值 。
来自 C11
标准,章节 §6.5.7。 , 移位运算符
The result of E1 << E2
is E1
left-shifted E2
bit positions; vacated bits are filled with zeros.
就是这样,在1
s的情况下,移位是可见的。
就是说,<
是 而不是 位移运算符(如您的代码中所示),<<
是。
<<
(不是 <
!)不移动一位。它移动了整数。当你说 1<<5
时,它向左移动 0000000000000001
五位(给定一个 16 位值),得到 0000000000100000
。 0<<5
将 0000000000000000
向左移动五个位置,结果是 0000000000000000
(即相同的值)。其他位不是不确定的:你不能移动一个位(我假设你想要像 ??????????1?????
和 ??????????0?????
这样的东西,但数字不是那样工作的。)
这看起来像是一个典型的 XY 问题。您可能想使用 data
来打开或关闭其他东西?询问 that。 (编辑:正如 Joachim Pileborg 在问题评论中所说的那样。)
好消息是 - 你想多了。
取整数,例如:01011011
。
左移 1:10110110
.
'whole thing'一起移位;零被移入 LSB。在右移的情况下,无符号数再次为零,或为有符号数实现定义:
The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.
(S6.5.7)
这意味着右移一个有符号数可能会导致算术移位或逻辑移位。
如果你想将 1
s 移到低端,而不是 0
s,只需使用一个位掩码来表示你移动的位置数。
移位操作是使用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 不同的值进行移位,您当然会得到不同的模式,但它会遵循相同的规则。 IE。所有位都会移位,无论它们是 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还有Rotate等精彩的位操作指令。)
是否可以像在 C 中的移位操作中移位 1
s 那样移位 0
s?
像这样
for (i=0; i<32; i++) {
if (data & 0x01) {
data |= (1<<i);
}
else {
data &=~ (0<<i);
}
}
我正在检查是否设置了某些位,并根据这些设置将 0
s 或 1
s 存储在新变量中,将每一位向左移动。
您不移动 0
或 1
,而是移动位值,无论是 0
还是 1
。换句话说,您移动 位位置 ,而不管其中存储的 值 。
来自 C11
标准,章节 §6.5.7。 , 移位运算符
The result of
E1 << E2
isE1
left-shiftedE2
bit positions; vacated bits are filled with zeros.
就是这样,在1
s的情况下,移位是可见的。
就是说,<
是 而不是 位移运算符(如您的代码中所示),<<
是。
<<
(不是 <
!)不移动一位。它移动了整数。当你说 1<<5
时,它向左移动 0000000000000001
五位(给定一个 16 位值),得到 0000000000100000
。 0<<5
将 0000000000000000
向左移动五个位置,结果是 0000000000000000
(即相同的值)。其他位不是不确定的:你不能移动一个位(我假设你想要像 ??????????1?????
和 ??????????0?????
这样的东西,但数字不是那样工作的。)
这看起来像是一个典型的 XY 问题。您可能想使用 data
来打开或关闭其他东西?询问 that。 (编辑:正如 Joachim Pileborg 在问题评论中所说的那样。)
好消息是 - 你想多了。
取整数,例如:01011011
。
左移 1:10110110
.
'whole thing'一起移位;零被移入 LSB。在右移的情况下,无符号数再次为零,或为有符号数实现定义:
The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type or if E1 has a signed type and a nonnegative value, the value of the result is the integral part of the quotient of E1 / 2E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.
(S6.5.7)
这意味着右移一个有符号数可能会导致算术移位或逻辑移位。
如果你想将 1
s 移到低端,而不是 0
s,只需使用一个位掩码来表示你移动的位置数。
移位操作是使用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 不同的值进行移位,您当然会得到不同的模式,但它会遵循相同的规则。 IE。所有位都会移位,无论它们是 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还有Rotate等精彩的位操作指令。)