按位运算?

时间:2014-10-24 22:18:14

标签: c bit-manipulation

我正在尝试编写一个宏来检查特定范围的位是打开还是关闭,用户可以输入数字,起始位和结束位。因此,如果用户输入十进制数字31,2,4,则必须检查2到4中的所有位是否为1,如果它们都是1,则返回true。如果它们不是全1,则返回false。在这种情况下,它们都是1,所以它将返回true

#define ALLON(X, S, E) //(MACRO HERE)

如何制作宏来执行此操作?

2 个答案:

答案 0 :(得分:1)

您可以使用一些基本位移位和按位逻辑运算来执行此操作。这样做:

#include <stdio.h>

#define ALLON(X,S,E) ((X & (~((~0U << E) | ~(~0U << (S - 1))))) == (~((~0U << E) | ~(~0U << (S - 1)))))

/*
    Or, simplifying with two macros...

    #define ALLMASK(S,E) (~((~0U << E) | ~(~0U << (S - 1))))
    #define ALLON(X,S,E) ((X & ALLMASK(S,E)) == ALLMASK(S,E))
*/

char * convert_to_8bit(char * buffer, const unsigned int n)
{
    size_t k = 0;
    for ( unsigned int i = 128; i > 0; i >>= 1 ) {
        if ( n & i ) {
            buffer[k++] = '1';
        }
        else {
            buffer[k++] = '0';
        }
    }
    return buffer;
}

int main(void)
{
    char buffer[9] = {0};

    printf("1 in binary is %s\n", convert_to_8bit(buffer, 1));
    printf("ALLON(1, 2, 4) is %s\n", ALLON(1, 2, 4) ? "true" : "false");
    printf("ALLON(1, 1, 1) is %s\n", ALLON(1, 1, 1) ? "true" : "false");

    printf("30 in binary is %s\n", convert_to_8bit(buffer, 30));
    printf("ALLON(30, 2, 4) is %s\n", ALLON(30, 2, 4) ? "true" : "false");
    printf("ALLON(30, 1, 1) is %s\n", ALLON(30, 1, 1) ? "true" : "false");
    printf("ALLON(30, 5, 5) is %s\n", ALLON(30, 5, 5) ? "true" : "false");
    printf("ALLON(30, 5, 6) is %s\n", ALLON(30, 5, 6) ? "true" : "false");

    return 0;
}

输出:

paul@horus:~/src/sandbox$ ./bs
1 in binary is 00000001
ALLON(1, 2, 4) is false
ALLON(1, 1, 1) is true
30 in binary is 00011110
ALLON(30, 2, 4) is true
ALLON(30, 1, 1) is false
ALLON(30, 5, 5) is true
ALLON(30, 5, 6) is false
paul@horus:~/src/sandbox$ 

简而言之,假设我们正在做ALLON(31,2,4):

  1. ~0U << E需要11111111并将其左移4,因此您获得11110000
  2. ~0U << (S - 1)需要11111111并将其左移1,因此您获得11111110
  3. ~(~0U << (S - 1))否定你刚刚做的事,给你00000001
  4. ORing这两个给你11110001,其中第2,3和4位是0。
  5. 否定为您提供00001110您感兴趣的位数为1。
  6. 如果与X进行AND运算等于掩码本身,则设置所有位。
  7. 这可能是一种较短的方式,但这种方式至少很容易理解。

答案 1 :(得分:0)

这样的事情:

#define GET_MASK(S, E)       (((1UL << (E - S + 1)) - 1) << S)

#define ALLOCN(X, S, E)      (((GET_MASK(S,E) & X) == GET_MASK(S,E)) ? 1 : 0)

下面, GET_MASK为您提供与您要检查的位相对应的掩码。如果在X else 0中设置了所有这些位,则ALLOCN返回1。 (假设位编号从0开始)

重要提示:此处没有检查是否有溢出。

希望这有帮助。