将n个最高位设置为twiddling

时间:2013-12-13 18:15:08

标签: c bit-manipulation

我有以下功能设置N个最高位,例如set_n_high(8)== 0xff00000000000000

uint64_t set_n_high(int n)
{
    uint64_t v = 0;
    int i;
    for (i = 63 ; i > 63 - n; i--) {
        v |= (1llu << i);
    }

    return v;
}

现在只是出于好奇,C中是否有任何方法可以在不使用循环(或查找表)的情况下完成相同的操作?

编辑:n = 0和n = 64是要处理的案例,就像循环变体一样。

6 个答案:

答案 0 :(得分:6)

如果您对n = 0案例无效,可以将其简化为

uint64_t set_n_high(int n)
{
    return ~UINT64_C(0) << (64 - n);
}

除此之外,如果您对“奇怪的移位计数”(未定义的行为,但在我的机器上工作)没问题,您可以进一步简化

uint64_t set_n_high(int n)
{
    return ~UINT64_C(0) << -n;
}

如果您对n = 64案例无效,可以将其简化为

uint64_t set_n_high(int n)
{
    return ~(~UINT64_C(0) >> n);
}

如果使用这意味着您必须验证n,则速度不会更快。否则,它可能是。

如果你不对任何一种情况都不行,那就太麻烦了。这是一个建议(可能有更好的方法)

uint64_t set_n_high(int n)
{
    return ~(~UINT64_C(0) >> (n & 63)) | -(uint64_t)(n >> 6);
}

请注意,否定无符号数是完全明确的。

答案 1 :(得分:5)

uint64_t set_n_high(int n) {
    return ((1llu << n) - 1) << (64-n);
}

答案 2 :(得分:2)

好好接受@ harold的回答并稍微改变一下:

 uint64_t set_n_high(int n)
{
int carry = n>>6;
return ~((~0uLL >> (n-carry)) >> carry);
}

答案 3 :(得分:2)

使用条件来处理n == 0然后它变得微不足道。

uint64_t set_n_high(int n) {
/*  optional error checking:
    if (n < 0 || n > 64) do something */
    if (n == 0) return 0;
    return -(uint64_t)1 << 64 - n;
}

没有什么比这更复杂的事情了。完全指定从intuint64_t的强制转换,以及否定和转移(因为如果n在[0,则保证移位量位于[0,63]中64])。

答案 4 :(得分:1)

嗯,我呈现的是一个奇怪的 :)

/* works for 0<=n<=64 */
uint64_t set_n_high(int n)
{
    return ~0llu << ((64 - n) / 4) << ((64 - n) * 3 / 4);
}

答案 5 :(得分:0)

对于它的价值,到目前为止的帖子(处理0-64的n),这个在x86_64和覆盆子pi上产生最少的组装(并且进行1分支操作)(使用gcc 4.8。 2)。它看起来也很可读。

uint64_t set_n_high2(int n) 
{
    uint64_t v = 0;

    if (n != 0) {
        v = ~UINT64_C(0) << (64 - n);
    }

    return v;
}