C - 如何返回所有偶数位设置为 1、所有奇数位设置为 0 的字?

标签 c bit-manipulation bitwise-operators

我只能使用这些运算符! 〜& ^ | + << >>

这是我到目前为止的代码,但我不知道如何让它工作

int setEvenBitsToOne(){
    int byte = 0x55;
    int word = byte | byte << 8;
    return word | word << 16;
}

最佳答案

由于整数的大小已知,因此可以对其进行硬编码。

int alternatingBits() {
    switch( sizeof(int) ) {
        case 2:
            return 0x5555;
        case 4:
            return 0x55555555;
        case 8:
            return 0x5555555555555555;
        default:
            fprintf(stderr, "Unknown int size: %zu\n", sizeof(int));
            exit(1);
    }
}

sizeof(int)是一个常量,因此编译器会将所有这些优化为常量。

但我假设这是一个小玩意儿的练习。首先我们需要的是只改变偶数位。这可以通过将位掩码设置为 1,将其添加到数字中,将掩码移动 2 个位置,然后再次添加来完成。

// C doesn't have a way to represent literal binary numbers,
// so I'm using the Perl convention.
num += 0b000001
num += 0b000100
num += 0b010000
...and so on...

位掩码移动为 mask = mask << 2 .

我们还需要知道何时停止。由于我们正在突破整数大小的限制,因此我们不想做类似 mask < INT_MAX 的事情。因为mask = mask << 2可能会溢出。相反,我们可以一次迭代整数 2 中的位数。

int alternatingBits() {
    /* Our number to start with */
    int num = 0;

    /* Our bitmask to add to the number */
    int mask = 1;

    /* The number of bits in an integer
       (to avoid clutering the for loop) */
    const int bits = sizeof(int) * 8;

    /* Step through each even bit */
    for( int i = 0; i < bits; i+=2 ) {
        /* Add the mask */
        num += mask;

        /* Shift the 1 over two bits */
        mask = mask << 2;
    }

    return num;
}

在这种情况下,@Olaf 在评论中提到了一个微妙的问题。当我们到达终点时,mask将比整数所能容纳的多移动一位。即使我们当时不使用它,它也会戳到 Undefined Behavior 的龙。这是编译器做任何它想做的事情的许可证。

我们需要确保不会发生这种情况,这意味着我们必须编写自己的修改版 for循环。

此外,整数的高位用于有符号,因此为了安全起见,我们应该将位掩码设置为无符号整数。

int alternatingBits() {
    int num = 0;
    unsigned int mask = 1;
    const int bits = sizeof(int) * 8;

    /* This does the same as a for loop, but lets us end before incrementing mask */
    int i = 0;
    while( 1 ) {
        num += mask;

        /* increment i and check if we're done before incrementing the mask */
        i += 2;
        if( i >= bits ) {
            break;
        }

        mask = mask << 2;
    }

    return num;
}

现在mask不会溢出,而且也不必担心签名位。

关于C - 如何返回所有偶数位设置为 1、所有奇数位设置为 0 的字?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42210508/

相关文章:

java - 按位左移行为

子进程通过管道发送一个数字,然后等待

c - 我质疑即使 struct iwreq 没有​​ ifr_name 作为成员,该代码是如何编译的

c++ - 二进制补码函数的问题

c++ - 解释下面的C++方法

php - CIDR 位运算 - 我可以更聪明一点吗?

c - 无符号返回类型返回有符号数 C

c - 为什么这个按位运算符结果为假?

c - 将线程绑定(bind)到处理器

c - 预期标识符或 '(' XCode C 指针函数