你好,我对按位运算符和移位有一些问题。我相信check_flag()是有效的,但set_flag()不是。有人能解释一下怎么回事吗?

#include <stdio.h>

void set_flag(int* flag_holder, int flag_position);
int check_flag(int flag_holder, int flag_position);

int main(int argc, char* argv[])
{
    int flag_holder = 0;
    int i;
    set_flag(&flag_holder, 3);
    set_flag(&flag_holder, 16);
    set_flag(&flag_holder, 31);
    for(i=31; i>=0; i--)
    {
        printf("%d", check_flag(flag_holder, i));
        if(i%4 == 0)
        {
            printf(" ");
        }
    }
    printf("\n");
    return 0;
}

void set_flag(int* flag_holder, int flag_position)
{
    *flag_holder = *flag_holder |= 1 << flag_position;
}

int check_flag(int flag_holder, int flag_position)
{
    int bit = (flag_holder << flag_position) & 1;
    if(bit == 0)
        return 0;
    else
        return 1;

    return bit;
}

最佳答案

您需要将flag_holder的类型更改为unsigned。假设您的ints是32位宽,当您设置高阶位(位置31)时,您是在设置符号位。这将导致右位移位的实现定义行为和左位移位的未定义行为。set_flag()函数应更改为:

void set_flag(unsigned* flag_holder, int flag_position)
{
    *flag_holder |= (1U << flag_position);
}

在将位设置为flag_position中的flag_holder之前,这会将位移到位置。1U是只设置了最低阶位的unsigned int位;(1U << flag_position)将单个设置位移到左侧。flag_position运算符相当于将按位或的结果和移位的位赋给|=。这也可以写成:
*flag_holder = *flag_holder | (1U << flag_position);

*flag_holder中也有问题。位移位码需要更改为:
int bit = (flag_holder >> flag_position) & 1U;

这会在使用*flag_holder运算符提取之前将感兴趣的位移到最低阶位置。用左移位的方式写时,check_flag()总是与&位比较。

关于c - C中的按位运算符和移位问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/41864691/

10-12 05:17