单位和多位的c位操作

时间:2012-05-11 19:26:09

标签: c macros bit-manipulation

我正在尝试在一个char中表示一堆值:前6位中的6个开/关标志,并使用后2位来保存4个不同的值。 这似乎是基本的,像这样的宏必须存在于某个地方,但我找不到它们。

 #define HOT 0x00
 #define BIG 0x01
 #define FAT 0x02
 #define HIT 0x03
 #define BAT 0x04
 #define ZAX 0x05    
 #define HOW 0x06

 #define TWO_BITS     nnn    // ???
 #define CONDITION_0  nnn   // bit combo: 00
 #define CONDITION_1  nnn   // bit combo: 01
 #define CONDITION_2  nnn   // bit combo: 10
 #define CONDITION_3  nnn   // bit combo: 11

void bitter(void)
{
    unsigned char myBits = 0;
    bool nonsense;

    if (myBits & BIG)  nonsense = true;    // BIG flag on   
    if (!(myBits & BAT)) nonsense = false; // BAT flag off

    myBits = myBits | BIG;     // turn on BIG bit
    myBits = myBits & ~BIG;    // turn off BIG bit

    if (TWO_BITS == CONDITION_0)
        doThis();
    else if (TWO_BITS == CONDITION_1_)
        doThat();
    // ... etc

}

那么用最后2位编写我想做的代码的最佳方法是什么?   我无法进行任何性能测试,因为我还没有想出如何编写代码,但我认为这是执行这些操作的最快方法。

[顺便说一句,这可能闻起来像家庭作业,但我只是一只54岁的狗试图学习一些新的技巧。]

3 个答案:

答案 0 :(得分:1)

我不确定我理解你想要什么,但听起来你想检查是否设置了两个位。在这种情况下,例如,如果你想检查最后两位是否都设置了,你可以这样做:

((myBits & 3) == 3)

答案 1 :(得分:1)

您只需要将位掩码应用于最后2位(0x03)并打开结果:

switch (myBits & 0x03) {
    case 0: // CONDITION_0
        doThis();
        break;
    case 1: // CONDITION_1
        doThat();
        break;
    case 2: // CONDITION_2
    case 3: // CONDITION_3
}

此外,如果您希望它们作为重用它们的宏:

#define CONDITION_0(X) (((X) & 0x03) == 0)
#define CONDITION_1(X) (((X) & 0x03) == 1)
#define CONDITION_2(X) (((X) & 0x03) == 2)
#define CONDITION_3(X) (((X) & 0x03) == 3)

然后你只需要写一些类似的东西:

if (CONDITION_0(myBits)) {
    doThis();
} else if (CONDITION_1(myBits)) {
    doThat();
}

答案 2 :(得分:1)

这取决于你是否需要自己处理这2位,作为0到3之间的(十进制)值,或者你总是将它们视为一个字节的高2位。

这是一种方法,我们只是屏蔽掉所有其他位,并将条件定义为2位将作为字节中高2位的值。

 #define TWO_BITS(x) ((x) & 0xC0)

 #define CONDITION_0  0
 #define CONDITION_1  0x40   // bit combo: 01
 #define CONDITION_2  0x80   // bit combo: 10
 #define CONDITION_3  0xC0   // bit combo: 11

也就是说,一个字节的高2位是二进制1 1 0 0 0 0 0 0,它是十六进制的0xC0。并且高2位为0 1,即一个字节中的所有位将为0 1 0 0 0 0 0 0,其为十六进制的0x40。

你的测试必须是

if (TWO_BITS(myBits) == CONDITION_0)

另一种方法是将那些高2位提取为2位整数(即0到3之间的值)。这很简单,只需将位置向右移动6位。

 #define TWO_BITS(x) ((x) >> 6)

 #define CONDITION_0  0x0
 #define CONDITION_1  0x01   // bit combo: 01
 #define CONDITION_2  0x02   // bit combo: 10
 #define CONDITION_3  0x03   // bit combo: 11

在测试其中一个条件时,用法是相同的。

 if (TWO_BITS(myBits) == CONDITION_0)

最后一点,似乎你的低6位标志有点不对,考虑例如。

#define HOW 0x06

0x06是二进制值0 0 0 0 0 1 1 0,因此实际上是打开或测试2位。您可能希望将1位与1个标志关联,这将是此序列

 #define BIG 0x01
 #define FAT 0x02
 #define HIT 0x04
 #define BAT 0x08
 #define ZAX 0x10
 #define HOW 0x20

这通常写成一个位移,因此很容易读出它是什么位:

 #define BIG (1 << 0)  //bit zero
 #define FAT (1 << 1)  //bit 1
 #define HIT (1 << 2)  //bit 2
 #define BAT (1 << 3)  //bit 3 , etc.
 #define ZAX (1 << 4)
 #define HOW (1 << 5)