2011-09-30 9 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

これらの文字列を常にハッシュとして '#define 'できますか? 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に書き込んで、インライン引用符付き文字列を新しい名前付き文字列定数に置き換えます。ファイルを作成する際の追加ステップとして、各文字列をハッシュすることもできます。作成したファイルを1つのファイルに含めることもできます。これにより、ハッシュされていないバージョンのファイル(ハッシュされていないデバッグバージョンとハッシュされたリリースバージョンを作成することができます)を作成できます。

これを試してみると、最初のパーサで文字列を検索すると、エッジケース(コメント、#include行、重複した文字列など)を処理する必要があります。

0

これを行うためのプリプロセッサを入手できない場合は、まずこの手順を実行するための独自のプリプロセッサを作成することができます。

+1

ええ、私はこれを検討しており、必要に応じてこれを行う予定ですが、できる限り標準のプリプロセッサを使用したいと考えています。 –

0

強制する方法はありませんが、コンパイラが十分あれば、それを行うことができます。その最適化オプションを試して、デバッガでコードの逆アセンブリを調べて、それらのどれかがあなたが望むものを達成できるかどうかを調べます。これを達成する

+3

あなたが話していることを行う単一のコンパイラに名前を付けることはできますか? –

+1

あなたがしなければならないのは、マクロそのものに完全なハッシュを書くことです。コンパイラはそれを定数式として見て、その値を(最適化設定が許せば)置き換えなければなりません。簡単!*(*ハード) – 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

文字列リテラルのハッシュ値を返すことは保証されていますか? –

関連する問題