使用8位整数作为标志掩码

时间:2019-07-11 04:52:21

标签: c bit-manipulation

对于自定义数据结构,我有65个不同的标志(选项)。当前看起来像这样:

struct CustomDataStruct {
    int Something;
    unsigned char Flags[9]
};

这样,我最多可以存储72个标志(剩下7个标志,以防万一我决定添加更多标志)。我想为每个标志使用一个单独的位,所以我想到了:

void SetFlag(struct CustomDataStructure* Struct, int FlagNr) {
    // Error checking and other stuff here
    int index = FlagNr / 8; array.
    Struct->Flags[index] |= 1 << (__________);

}

我已经尝试使用1 << (FlagNr % 8),但是它没有设置正确的位。例如,我想打开标志ID 23(从零开始),所以我调用SetFlag(structInstance, 23),它可以正确确定索引(Flags [2]),但是23 % 8 = 71 << 7 = 1000 0000(二进制),而不是正确的值0000 0001(打开数组第3个uchar的最后一位,即第24位) )。

标记必须存储在此数组中,每一位代表标志开关。不能更改此选项。

3 个答案:

答案 0 :(得分:3)

通常从最低有效(最右边)的位开始对位进行索引,因为在大多数情况下,这样做更有意义。如果您想扭转这种情况,只需执行1 << (7 - FlagNr % 8)0x80 >> (FlagNr % 8)

答案 1 :(得分:3)

而不是进行移位,而是轻松进行数组查找。 FlagNr包含从零开始的位索引,因此值0为第一个数组元素中的第一位。

void setFlag( struct CustomDataStructure* thing, int FlagNr) {
    static uint8_t  masks[] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
    size_t   index = FlagNr % 8;
    size_t   xndex = FlagNr / 8;
    thing->Flags[xndex] |= masks[index];
}

答案 2 :(得分:1)

void setFlag( struct CustomDataStructure* foo, int flagIndex ) {

    assert( flagIndex >= 0 && flagIndex < 72 ); // Defensive programming!

    size_t arrayIndex = flagIndex / 8;
    int    bitShift   = flagIndex % 8;

    // If you want reverse (little-endian) bit order then subtract from 7:
    bitShift = 7 - bitShift;

    // This code is expanded for readability. An optimizing-compiler will still generate fast code:
    uint8_t flags = foo->Flags[ arrayIndex ];
    flags = flags | ( 1 << bitShift );
    foo->Flags[ arrayIndex ] = flags;
}