对于自定义数据结构,我有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
= 7
和1 << 7
= 1000 0000
(二进制),而不是正确的值0000 0001
(打开数组第3个uchar的最后一位,即第24位) )。
标记必须存储在此数组中,每一位代表标志开关。不能更改此选项。
答案 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;
}