2013-03-12 90 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

如果您知道所有枚舉的值,那麼您可以計算所有枚舉的日誌並將它們存儲在緩衝區中。或者,你可以寫所有的日誌。值(您將要使用)在一個文件中並讀取該文件以生成表格;這樣你就可以計算出日誌。值僅爲第一次。

相關問題