c中的按位运算符和移位问题

时间:2017-01-26 01:43:24

标签: c bit-manipulation bit

您好我在按位运算符和移位方面遇到了一些问题。我相信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;
}

1 个答案:

答案 0 :(得分:2)

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

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

在将flag_position设置为flag_holder之前,这会将位移位。 1Uunsigned int,只设置了最低位; (1U << flag_position)将单个位flag_position位置向左移动。 |=运算符相当于将*flag_holder的按位的结果和移位的位分配给*flag_holder。这也可以写成:

*flag_holder = *flag_holder | (1U << flag_position);

check_flag()也存在问题。位移代码需要更改为:

int bit = (flag_holder >> flag_position) & 1U;

在使用&运算符提取之前,这会将感兴趣的位移动到最低位置。它的编写方式是左移,&始终与0位进行比较。