uint64_t将位数范围设置为1

时间:2018-01-25 06:11:31

标签: c

我正在尝试使用高和低来源创建一个将位数范围更改为全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;
}

2 个答案:

答案 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)

unsignedunsigned int,因此为32位值,以及为{em> signed int的常量1,因此当您正在转移{ {1}}你是在32位整数上做的。

在轮班期间使用1 << (high-low + 1)所有常量转换为无符号64位int。

ull