位运算:相似运算结果不同
Bit operation: Similar operation results in different results
以下这段代码没有计算出我认为它应该具有的值:
#include <stdio.h>
#include <stdint.h>
int main(void) {
uint32_t var = 0x55555555;
uint32_t res1 = (var & (0x3 << (15*2)) >> (15*2));
uint32_t res2 = (var & (0x3 << (14*2)) >> (14*2));
printf("result1 = 0x%08x\n", res1);
printf("result2 = 0x%08x\n", res2);
return 0;
}
输出:
结果 1 = 0x55555555
结果 2 = 0x00000001
谁能解释为什么在执行完全相同的操作时 result1 和 result2 会不同?我在执行位移和位与时做错了什么?
15 *2 = 30。0x3 = 2 位 -> 设置 uint32 中的最高位。因为 0x3 是有符号的,所以这是一个负数。将其向下移动 30 位得到 0xFFFFFFFFF。当然,如果将 0x3 向上移动 28 位然后再次向下移动,则不会发生同样的情况。
如果你真的想分别在位 31&30 和位 29&28 中挑出两位,我会这样做:
uint32_t res1 = (var >> (15*2)) & 0x3;
uint32_t res2 = (var >> (14*2)) & 0x3;
除了"more correct"。
这也节省了一个班次
0x3的类型是signed int。 C 标准说:
The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. [...] If E1 has a signed type and nonnegative value, and E1 × 2^E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
0x3 * 2^30 不能用整数表示。
将常量更改为 0x3U,您将得到正确的行为。
在这个表达式中
(var & (0x3 << (15*2)) >> (15*2))
整数常量 0x3
的类型为 int
。此操作后
(0x3 << (15*2))
设置结果整数值的符号位。
此操作后
(0x3 << (15*2)) >> (15*2)
实现(它是实现定义的)向右传播符号位。所以结果表达式的所有位都已设置。
你会得到
var & 0xFFFFFFFF
将产生 var
.
在第二个表达式中符号位未设置且运算后
(0x3 << (14*2)) >> (14*2)
你会得到0x3
0x55555555 & 0x3
将产生 1。
以下这段代码没有计算出我认为它应该具有的值:
#include <stdio.h>
#include <stdint.h>
int main(void) {
uint32_t var = 0x55555555;
uint32_t res1 = (var & (0x3 << (15*2)) >> (15*2));
uint32_t res2 = (var & (0x3 << (14*2)) >> (14*2));
printf("result1 = 0x%08x\n", res1);
printf("result2 = 0x%08x\n", res2);
return 0;
}
输出:
结果 1 = 0x55555555
结果 2 = 0x00000001
谁能解释为什么在执行完全相同的操作时 result1 和 result2 会不同?我在执行位移和位与时做错了什么?
15 *2 = 30。0x3 = 2 位 -> 设置 uint32 中的最高位。因为 0x3 是有符号的,所以这是一个负数。将其向下移动 30 位得到 0xFFFFFFFFF。当然,如果将 0x3 向上移动 28 位然后再次向下移动,则不会发生同样的情况。
如果你真的想分别在位 31&30 和位 29&28 中挑出两位,我会这样做:
uint32_t res1 = (var >> (15*2)) & 0x3;
uint32_t res2 = (var >> (14*2)) & 0x3;
除了"more correct"。
这也节省了一个班次0x3的类型是signed int。 C 标准说:
The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. [...] If E1 has a signed type and nonnegative value, and E1 × 2^E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
0x3 * 2^30 不能用整数表示。
将常量更改为 0x3U,您将得到正确的行为。
在这个表达式中
(var & (0x3 << (15*2)) >> (15*2))
整数常量 0x3
的类型为 int
。此操作后
(0x3 << (15*2))
设置结果整数值的符号位。
此操作后
(0x3 << (15*2)) >> (15*2)
实现(它是实现定义的)向右传播符号位。所以结果表达式的所有位都已设置。
你会得到
var & 0xFFFFFFFF
将产生 var
.
在第二个表达式中符号位未设置且运算后
(0x3 << (14*2)) >> (14*2)
你会得到0x3
0x55555555 & 0x3
将产生 1。