我的枚举是这样的:
enum my_enum
{
first_val = (1LLU << 0),
second_val = (1LLU << 1),
...
last_val = first_val = (1LLU << 63)
};
但通过这种方式,我只能使用 64 个值,问题是我如何在我的情况下和一个枚举中处理超过 64 个值?
谢谢。
最佳答案
根据C11 6.7.2.2枚举说明符/2
(我的粗体):
The expression that defines the value of an enumeration constant shall be an integer constant expression that has a value representable as an int.
因此,当前拥有 N
位宽的枚举的唯一方法是,如果您的 int
类型是 N
位宽。当前,您很难找到具有比 64 位 int
值更好的实现(尽管我毫不怀疑它们即将到来)。
枚举可能比位掩码更适合连续值。如果您想要执行任意大小的位掩码,您应该考虑使用无符号整数类型的数组,最好是像 uint8_t
这样的固定大小,以简化处理。
以下例程可能是一个好的开始。首先,所需的 header 、结构和辅助数组:
#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__
关于c - 处理枚举按位大小大于 64,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27226692/