2011-09-30 111 views
8

我目前正在研究一個代碼項目,要求我用這些字符串的散列替換某些字符串。由於這些字符串在運行時不會改變,因此讓c預處理器對我聲明在編譯時被哈希的每個字符串運行我的哈希函數將是有利的,效率明智的。如何讓C預處理器在編譯期間執行代碼?

有什麼辦法讓編譯時運行我的散列函數的預處理器?C

我知道這並不是我上面描述的方式,但只是想知道我要去哪裏,這裏有一些使用宏的僞代碼。試想一下,而不是簡單地擴大宏,預處理器運行散列函數,並將其擴展到該散列函數的返回值:

#include <iostream> 
    #include <string> 

    #define U64_HASH(inputString) getU64HashCode(inputString) 

    //my hash function 
    unsigned long long getU64HashCode (string inputString) 
    { 
     /*code*/ 
    } 

    int main() 
    { 
     cout << U64_HASH("thanks for helping me") << endl; 
     return 0; 
    } 

再次,理想的cout << U64_HASH("thanks for helping me") << endl;將擴大到cout << 12223622566970860302 << endl;

我寫的一個頭文件生成器,並且這個項目工作正常。

最終解決

我已經決定使用John Purdy's perl script這個項目,因爲它只是真棒,並讓我給我希望直接輸出喂到我的編譯器。非常感謝,約翰。

+0

並非沒有瘋魔。 –

+0

C++ 11具有用戶定義的文字和constexpr。這些可能會有所幫助。 – Pubby

+1

你總是可以將這些字符串定義爲哈希值? AFAIK C預處理器沒有任何運行代碼的能力。 – Serdalis

回答

6

一種方法是把所有的字符串放到一個頭文件,並將它們命名爲:

// StringHeader.h 
#define helloWorld    "Hello World" 
#define error_invalid_input  "Error: Invalid Input" 
#define this_could_get_tedious "this could get tedious" 

然後就可以使用這些字符串:

#include "StringHeader.h" 
std::cout << this_could_get_tedious << std::endl; 

然後你就可以運行程序在您的StringHeader.h上散列每個字符串,並生成替換頭文件:

// Generated StringHeader.h 
#define helloWorld    097148937421 
#define error_invalid_input  014782672317 
#define this_could_get_tedious 894792738384 

起初,這看起來非常手動和乏味,但有辦法使它自動化。

例如,你可以寫一些東西來解析你的源代碼,尋找「引用字符串」。然後它可以命名每個字符串,將其寫入一個StringHeader.h,並用新的命名字符串常量替換內聯帶引號的字符串。作爲創建文件的附加步驟,您可以對每個字符串進行散列 - 或者在創建文件後,您可以一次性將文件散列。這可以讓你創建一個哈希和非哈希版本的文件(這可以很好地創建一個非哈希的Debug版本,以及散列版本)。

如果你這樣做,你的初始解析器查找字符串將不得不處理邊緣情況(註釋,#包括行,重複的字符串等)。

0

如果你不能讓預處理器爲你做這件事,你可以編寫你自己的預處理器來先做這一步。

+1

是的,我正在考慮這一點,如果有必要的話會這樣做,但如果可以的話,我真的很想使用標準預處理器。 –

0

有沒有辦法強制它,但如果你的編譯器足夠好,它可以做到這一點。玩它的優化選項,並研究調試器中的代碼反彙編,看看它們中的任何一個是否可以讓你實現你想要的。要做到這一點

+3

你可以命名一個編譯器來執行你正在談論的內容嗎? –

+1

所有你必須做的事情是在宏本身中寫入完整的散列 - 然後編譯器應該將它看作一個常量表達式並替換該值(假設優化設置允許)。 Easy!*(* hard) – geofftnz

+0

@David:我認爲DMD編譯器可以通過CTFE做到這一點:)雖然我也很好奇它是否可以在C++中使用。從未聽說過 –

6

如果編譯器曾經支持這一點,C++ 11 user defined literals

constexpr unsigned long long operator "" U64_HASH_(
    const char *literal_string) { ... } 

#define U64_HASH(inputString) inputString U64_HASH_ 

constexpr

constexpr unsigned long long operator "" U64_HASH(
    const char *literal_string) { ... } 
+0

這是否保證返回字符串文字的哈希值? –

相關問題