2013-03-12 63 views
3

我有两个枚举正是如此定义当索引不连续时,设置查找表的最佳方式是什么?

enum foo { 
    foo_a = 0x1, 
    foo_b = 0x2, 
    foo_c = 0x4, 
    foo_d = 0x8, 
    foo_e = 0x10, 
    ..etc.. 
} 

enum bar { 
    bar_a = 0x1, 
    bar_b = 0x2, 
    bar_c = 0x4, 
    bar_d = 0x8, 
    bar_e = 0x10, 
    ..etc.. 
} 

现在,有foo_之间[AZ] bar_ 1对1的映射和[AZ],我想看看它迅速起来。最明显的方式做到这一点是做一些声明类似

int table[][] = { 
    [foo_a] = bar_c, 
    [foo_b] = bar_a, 
    [foo_c] = bar_b, 
    ..etc.. 
} 

,只是看它使用result = table[(enum foo)temp]。但由于这些枚举已被逐位声明,所以table的大小呈指数增长。

有没有更简单的方法来设置编译时的东西?

有一件事我认为做这样的事情

int table[][] = { 
    [LOG(foo_a)] = bar_c, 
    [LOG(foo_b)] = bar_a, 
    [LOG(foo_c)] = bar_b, 
    ..etc.. 
} 

这将减少内存占用,但我不知道反正来计算LOG在编译时。

其他建议?

我唯一的限制是以下内容,我无法修改枚举,因为更改它们会导致二进制不兼容。

编辑:编译时的解决方案首选

+0

,我不得不问,你在计划什么“寻找(foo_a | foo_b)(这是首先使用位列作为唯一合乎逻辑的理由)的多位值的“*”替换为*。 – WhozCraig 2013-03-12 03:35:17

+2

这些枚举是否真的具有*相同*可能的值?你可以从一个枚举类型转换为另一个变量吗? – chrisaycock 2013-03-12 03:37:26

+0

@WhozCraig API实际上设计不正确。这些价值从来都不是要一起编辑的。我不明白他们为什么从来不打扰他们的顺序编号。 – 2013-03-12 03:40:18

回答

3

是的,你可以“计算日志在编译时”,只要参数是二的幂:

#define LOG2P2(m) (((m)-1)/(((m)-1)%255+1)/255%255*8 + 7-86/(((m)-1)%255+12)) 

此工程的m值高达约2 ** 2040(远大于任何类型的在现实世界的C语言实现),而且也为更大的价值在那里我得到这个从这样的作品,在回答以下问题的一个版本:在您考虑的快捷方式,这

https://stackoverflow.com/a/4589384/379897

+0

谢谢!进一步挖掘,我发现了Linux内核的更可靠的实现方式ilog2 @ http://lxr.free-electrons.com/source/include/linux/log2.h。无论如何,由于我正在编写驱动程序,所以这有点方便。 – 2013-03-12 04:09:39

1

只是要对一个表:

int table[2][] = { 
    { foo_a, bar_c }, 
    { foo_b, bar_a }, 
    /* ... */ 
}; 

现在排序它,如果你想,把它复制到被第二排序的第二表值进行反向查找。如果表格只有十几个元素,则执行线性搜索;如果表格很大,则使用bsearch()

0

如果您知道所有枚举的值,那么您可以计算所有枚举的日志并将它们存储在缓冲区中。或者,你可以写所有的日志。值(您将要使用)在一个文件中并读取该文件以生成表格;这样你就可以计算出日志。值仅为第一次。

相关问题