将n个最高位设置为twiddling

use*_*970 7 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;
}
Run Code Online (Sandbox Code Playgroud)

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

编辑:n = 0和n = 64是要处理的情况,就像循环变体一样.

har*_*old 6

如果您对n = 0案例不起作用没问题,可以将其简化为

uint64_t set_n_high(int n)
{
    return ~UINT64_C(0) << (64 - n);
}
Run Code Online (Sandbox Code Playgroud)

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

uint64_t set_n_high(int n)
{
    return ~UINT64_C(0) << -n;
}
Run Code Online (Sandbox Code Playgroud)

如果您对n = 64案例不起作用没问题,可以将其简化为

uint64_t set_n_high(int n)
{
    return ~(~UINT64_C(0) >> n);
}
Run Code Online (Sandbox Code Playgroud)

如果使用这意味着你必须验证n,它将不会更快.否则,它可能是.

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

uint64_t set_n_high(int n)
{
    return ~(~UINT64_C(0) >> (n & 63)) | -(uint64_t)(n >> 6);
}
Run Code Online (Sandbox Code Playgroud)

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

  • 我唯一不满意的是我的电脑爆炸了. (2认同)

jwo*_*der 5

uint64_t set_n_high(int n) {
    return ((1llu << n) - 1) << (64-n);
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这不是原始代码的替代品.注意当n = 0且n = 64时出现的守护进程 (3认同)