C中的位操作

时间:2009-12-09 12:08:58

标签: c bit-manipulation

所以如果我有一个32位的整数。前28位(左起)用于存储内存块的大小,接下来的两位是0,最后两位是:

  • 存储if if是最后一个节点然后
  • 如果使用或不使用(分别),则存储。

我要做的是知道如何在isLast操作和isUsed操作上打开和关闭标志。

(如果我们只考虑最后两个整数(再次,我们从左开始)那么01将不是最后一个并且例如被使用,再一个例子是11是最后一个并且被使用,00不是最后并且不被使用。 )

我希望能够以一种简单的方式打开和关闭标志。我知道我需要使用位操作,包括&和|但我不确定如何。

如果您需要更多问题描述,请向我提问。

7 个答案:

答案 0 :(得分:11)

//turn on isUsed
data |= 1;
//turn off isUsed
data &= ~1;
//turn on notLast
data &= ~2;
//turn off notLast
data |= 2;

答案 1 :(得分:9)

这很简单:

/* Turn on bit 0 */
code = code | 1;

/* Turn off bit 0 */
code = code & ~1;

/* Turn on bit 1 */
code = code | 2;

/* Turn off bit 1 */
code = code & ~2;

请参阅Bitwise operators in C或Google了解相应的条款。您可以在任何关于C的书籍或教程中找到这个。

答案 2 :(得分:5)

通常,将最低有效位计为0,设置位N,需要将原始值与1<< N.

例如设置第1位:

val |= (1 << 1);

要清除位N,您需要将原始值与1&lt;&lt;&lt;&lt;&lt; N.

例如清除第1位:

val &= ~(1 << 1);

答案 3 :(得分:4)

这是一个接口,无论是函数还是宏,如:

// Use unsigned ints (assuming that's your 32-bit type).

#define setLast(x)   (x) |=  2
#define clrLast(x)   (x) &= ~2
#define isLast(x)    ((x) &  2)

#define setUsed(x)   (x) |=  1
#define clrused(x)   (x) &= ~1
#define isUsed(x)    ((x) &  1)

您还可以提供宏来提取大小部分并创建整数:

#define getSize(x) ((x) >> 4)
#define create (sz,last,used) \
    (((sz) & 0x0fffffff) << 4) | \
    (((last) & 1) << 1) | \
    (((used) & 1))

如果您提供“功能”来完成工作并为其提供合理的名称,您会发现您的代码变得更具可读性。否则,您的代码中会添加难以理解的位操作指令。

请记住宏的常规规则,如果你的宏不止一次使用它就不会传递x++之类的东西(这里实际上不是这种情况)。如果你想要超级安全,你可以将它们作为功能。

等效函数将是:

unsigned int setLast (unsigned int *x) { *x |=  2; return *x; }
unsigned int clrLast (unsigned int *x) { *x &= ~2; return *x; }
unsigned int isLast  (unsigned int  x) { return x & 2; }

unsigned int setUsed (unsigned int *x) { *x |=  1; return *x; }
unsigned int clrUsed (unsigned int *x) { *x &= ~1; return *x; }
unsigned int isUsed  (unsigned int  x) { return x & 1; }

unsigned int getSize (insigned int  x) { return x >> 4; }
unsigned int create  (unsigned int sz, unsigned int last, unsigned int used) {
    unsigned int ret =
        ((sz & 0x0fffffff) << 4) |
        ((last & 1) << 1) |
        ((used & 1));
    return ret;
}

答案 4 :(得分:3)

打开标志:

register |= (1<<LAST_BIT);

关掉旗帜:

register &= ~(1<<LAST_BIT);

另一种方法是使用union位字段:

union
{
  uint32_t value;
  struct
  {
    unit32_t body:28;
    unit32_t reserved:2;
    unit32_t last_bit:1;
    unit32_t used_bit:1;
  } fields;
} MyResister;

MyResister.fields.last_bit = 1;
MyResister.fields.used_bit = 0;

答案 5 :(得分:0)

我会抛出一个BIT(x)宏,只是为了让源代码更清晰:

#define BIT(n) (0x1U << (n))

哪会导致:

#define LAST_SET(x) ((x) |= BIT(1))
#define LAST_CLR(x)  ((x) &= ~BIT(1))

另外,如前所述,总是将参数放在括号中。

(OT)编辑:改变了宏的名称,因为我不喜欢先使用动词。首先,像getWhatever这样的函数用于代码,您可以在该类中对函数进行分组。在C,恕我直言,您应该首先放置“组件”名称,例如timeGet()et c

(OT2)此外,如果它是一个像这样的寄存器宏制作很好,这将导致更好的可移植性:

#define MY_REG_RD() (MY_REG)
#define MY_REG_WR(x) (MY_REG = (x))
#define MY_REG_SET(x) (MY_REG |= (x))
#define MY_REG_CLR(x) (MY_REG &= ~(x))
#define MY_REG_DIS BIT(10)
#define MY_REG_EN BIT(4)

然后你可以这样做:

MY_REG_SET(MY_REG_EN);

答案 6 :(得分:0)

bool isBitOn( int mask , int i ){ // returns True if i-Th bit is On
    return mask & ( 1 << i ) ;
}

int BitOn( int mask , int i ){ // Turn On the i-Th bit of the value and then returns it
    return mask | ( 1 << i ) ;
}

int BitOff( int mask , int i ){ // Turn Off the i-Th bit of the value and then returns it
    return mask - ( 1 << i ) ;
}

int BitToggle( int mask , int i ){ // Toggle the i-Th bit of the value and then returns it
    return mask ^ ( 1 << i ) ;
}

void printbit(int n) { // print the Binary representation of a Integer Number
    for(int i = 31 ; i >=0 ; i-- )
        printf("%d", isBitOn(n,i) );
    printf("\n");
}