我的枚举是这样的:
enum my_enum
{
first_val = (1LLU << 0),
second_val = (1LLU << 1),
...
last_val = first_val = (1LLU << 63)
};
但是这样我只能使用64个值,问题是如何在我的情况下和一个枚举中处理超过64个值?
谢谢。
答案 0 :(得分:3)
根据C11 6.7.2.2 Enumeration specifiers /2
(我的大胆):
定义枚举常量值的表达式应为整数常量表达式,具有可表示为int的值。
因此,如果N
类型为int
位宽,则当前枚举N
位宽的唯一方法是。你现在很难找到一个优于64位int
值的实现(尽管我不怀疑他们会来)。
枚举可能更适合连续值而不是位掩码。如果你想做任意大小的位掩码,你应该考虑一组无符号整数类型,最好是固定大小,如uint8_t
,以简化你的处理。
以下例程可能是一个好的开始。首先,需要的头文件,结构和帮助器数组:
#include <stdlib.h>
#include <stdint.h>
typedef struct {
size_t sz;
uint8_t data[];
} tBitSet;
uint8_t bitMask[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
接下来,分配和释放功能:
tBitSet *bitAlloc (size_t sz) {
size_t sz8 = (sz + 7) / 8;
tBitSet *bits = malloc (sizeof (tBitSet) + sz8);
if (bits != NULL) {
bits->sz = sz;
for (size_t pos = 0; pos < sz8; pos++)
bits->data[pos] = 0;
}
return bits;
}
void bitFree (tBitSet *bits) {
free (bits);
}
第三,设置,清除,切换和测试的功能:
void bitSet (tBitSet *bits, size_t pos) {
if (pos < bits->sz)
bits->data[pos / 8] |= bitMask[pos % 8];
}
void bitClear (tBitSet *bits, size_t pos) {
if (pos < bits->sz)
bits->data[pos / 8] &= ~bitMask[pos % 8];
}
void bitToggle (tBitSet *bits, size_t pos) {
if (pos < bits->sz)
bits->data[pos / 8] ^= bitMask[pos % 8];
}
int bitTest (tBitSet *bits, size_t pos) {
if (pos < bits->sz)
return ((bits->data[pos / 8] & bitMask[pos % 8]) == 0) ? 0 : 1;
return 0;
}
当然,最后还有一个测试工具,用于检查我是否给了你伪造的代码: - )
#include <stdio.h>
void bitDump (char *desc, tBitSet *bits) {
printf ("%s:", desc);
for (size_t pos = 0; pos < (bits->sz + 7) / 8; pos++)
printf (" $%02x", bits->data[pos]);
putchar (':');
for (size_t pos = 0; pos < bits->sz; pos++) {
if ((pos % 8) == 0)
putchar (' ');
printf ("%d", bitTest (bits, pos));
}
for (size_t pos = bits->sz; (pos % 8) != 0; pos++)
putchar ('_');
putchar ('\n');
}
#define SZ 30
int main (void) {
tBitSet *bits = bitAlloc (SZ);
if (bits == NULL) {
puts ("Could not allocate bitset");
return 1;
}
bitDump ("Initial ", bits);
for (size_t pos = 0; pos < SZ; pos++) bitSet (bits, pos);
bitDump ("Set all ", bits);
for (size_t pos = 1; pos < SZ; pos += 2) bitClear (bits, pos);
bitDump ("Clear every two ", bits);
for (size_t pos = 0; pos < SZ; pos++) bitToggle (bits, pos);
bitDump ("Toggle all ", bits);
for (size_t pos = 1; pos < SZ; pos += 2) bitClear (bits, pos);
bitDump ("Clear every two ", bits);
for (size_t pos = 4; pos < SZ; pos += 5) bitSet (bits, pos);
bitDump ("Set every five ", bits);
for (size_t pos = 0; pos < SZ; pos++) bitToggle (bits, pos);
bitDump ("Toggle all ", bits);
for (size_t pos = 0; pos < SZ; pos += 2) bitClear (bits, pos);
bitDump ("Clear odd ", bits);
for (size_t pos = 1; pos < SZ; pos += 2) bitClear (bits, pos);
bitDump ("Clear even ", bits);
bitFree (bits);
return 0;
}
其输出显示了它的工作原理:
Initial : $00 $00 $00 $00: 00000000 00000000 00000000 000000__
Set all : $ff $ff $ff $fc: 11111111 11111111 11111111 111111__
Clear every two : $aa $aa $aa $a8: 10101010 10101010 10101010 101010__
Toggle all : $55 $55 $55 $54: 01010101 01010101 01010101 010101__
Clear every two : $00 $00 $00 $00: 00000000 00000000 00000000 000000__
Set every five : $08 $42 $10 $84: 00001000 01000010 00010000 100001__
Toggle all : $f7 $bd $ef $78: 11110111 10111101 11101111 011110__
Clear odd : $55 $15 $45 $50: 01010101 00010101 01000101 010100__
Clear even : $00 $00 $00 $00: 00000000 00000000 00000000 000000__