我正在尝试使用高和低来源创建一个将位数范围更改为全1的方法。代码工作在0到30之间,然后输出错误的数字。 setBits(0,31,0)的正确结果应该是ffffffff而不是0。
是什么导致我的代码重置为零?
setBits(0,0,0): 1
setBits(0,1,0): 3
setBits(0,2,0): 7
setBits(0,3,0): f
setBits(0,4,0): 1f
setBits(0,5,0): 3f
setBits(0,6,0): 7f
setBits(0,7,0): ff
setBits(0,8,0): 1ff
setBits(0,9,0): 3ff
setBits(0,10,0): 7ff
setBits(0,11,0): fff
setBits(0,12,0): 1fff
setBits(0,13,0): 3fff
setBits(0,14,0): 7fff
setBits(0,15,0): ffff
setBits(0,16,0): 1ffff
setBits(0,17,0): 3ffff
setBits(0,18,0): 7ffff
setBits(0,19,0): fffff
setBits(0,20,0): 1fffff
setBits(0,21,0): 3fffff
setBits(0,22,0): 7fffff
setBits(0,23,0): ffffff
setBits(0,24,0): 1ffffff
setBits(0,25,0): 3ffffff
setBits(0,26,0): 7ffffff
setBits(0,27,0): fffffff
setBits(0,28,0): 1fffffff
setBits(0,29,0): 3fffffff
setBits(0,30,0): 7fffffff
setBits(0,31,0): 0
uint64_t setBits(unsigned low, unsigned high, uint64_t source)
{
assert(high < 64 && (low <= high));
uint64_t mask;
mask = ((1 << (high-low + 1))-1) << low;
uint64_t extracted = mask | source;
return extracted;
}
答案 0 :(得分:1)
您需要将初始位设置为unsigned long long
(或uint64_t
)类型,以便在位移位时不会溢出。
mask = ((1ULL << (high - low + 1)) - 1) << low;
^^^
对于int
类型的数字1,当lefthifted为32位时它会溢出:
((1 << (high-low + 1))-1) // Where (high-low + 1) == 31 - 0 + 1 == 32
^
00000000 00000000 00000000 00000001 = 1
v <-- Left shift for 32 bits --------<
(1) 00000000 00000000 00000000 00000000 = 0
但这适用于64位整数类型。因此,将其更改为1ULL
,问题就消失了。
答案 1 :(得分:1)
unsigned
为unsigned int
,因此为32位值,以及为{em> signed int的常量1
,因此当您正在转移{ {1}}你是在32位整数上做的。
在轮班期间使用1 << (high-low + 1)
将所有常量转换为无符号64位int。
ull