2012-01-16 12 views
4

C言語では、ブロック暗号の暗号化ルーチンと復号化ルーチンの両方を実装する関数があります。双方の共通の命名と利用規約を維持するために、後に2つの異なる機能へのルーチンを分離する可能性を開いたままにするために、私は次のようやった:そのI」を除いて、正常に動作しますC:静的関数を隠すパブリックエイリアス

void cipher(char *out, const char *in); 
#define encrypt cipher 
#define decrypt cipher 

実際の関数(cipher)を隠すのが大好きなので、人々はencryptまたはdecryptを使用しなければなりません。今、cipherはパブリックインターフェイスの一部なので、後で2つの異なる関数に分割してcipherを削除することにした場合、厳密に言えば、私はインターフェイスを破棄しています。しかし、もし私がcipherを隠すことができるのであれば、encryptdecryptだけがインターフェイスの一部です。私は(

私がこれまでに作ってみた唯一のオプションは、cipherは、静的行い、cipherを呼び出すためにencryptdecryptの実際の機能を実装しているが、私は追加のオーバーヘッドが実際に価値があることはよく分かりませんできるだけタイトなコードサイズを維持しようとすると、この同じ問題が複数発生します)。

私は関数ポインタでできることはありますか?他のアイデア?

+1

どのようにstaticとしてヘッダファイルに 'encrypt'と' decrypt'の定義について'cipher'を呼び出すインライン関数?これはあなたにソースの互換性を与えるでしょう( 'cipher'がシンボルテーブルにあるからといってそれがAPIにあるわけではないからです)、後で' cipher'をdllから取り除くとバイナリ互換性はありません。 –

+1

ああ、btw、何もしないラッパー関数を呼び出すと、測定可能なオーバーヘッドが生成された場合、ブロック暗号は弱くなります;-p –

+0

@Steve:うーん、それはうまくいくが、警告( "暗黙の関数宣言"暗号 '')。その場合、誰かが 'cipher'を直接呼び出すことができます。ヘッダーファイルにはありません。だから私はそれが問題になっていると思いますが、それは私には悪いことです。これを防ぐために 'cipher'を' static'とマークするとリンクされません。 – brianmearns

答えて

2

あなたは、関数ポインタを使用することができます

static void cipher(...); 

void (*encrypt)(...) = cipher; 
void (*decrypt)(...) = cipher; 

少なくとも典型的な使用(ユーザーがちょうどencrypt(whatever);を使用しています)で、これは通常は見えません。唯一の明白な問題は、上で定義したように、ポインタは書き込み可能なままなので、ユーザーは他の関数のアドレスで間違って上書きすることができないようにすることがあります。const

#define encrypt(x, y) private_cipher_((x), (y)) 
#define decrypt(x, y) private_cipher_((x), (y)) 

これに対して確保すべきである:

別の可能性は、名前cipher公衆いると一緒に暮らす(またはprivate_cipher_のようなものに名前を変更不慮の名前の衝突を避けるため)、その後、ちょうどマクロのカップルを使用することですオーバーヘッド。

+0

マクロは私が今使っているものですが、私は 'cipher'を隠したいと思っています。私は関数ポインタを使用することが私の最善の策だと思います。私はそれをテストし、うまくいきます。 'encrypt'と' decrypt'を 'const'としてマークすることができますので、変更できません。' cipher'を 'static'とマークしてインポートできないようにします。それはオーバーヘッドを少し追加するだけですが、それがどこで定義されているかではなく、どこで呼び出されるのですか。だから、より良いトレードオフを決定する必要があります。 – brianmearns

0

GCCを使用している場合、alias attributeを使用して、cipher機能を指す2つのエイリアスを作成できます。

しかし、Steve Jessopのコメントを念頭に置いて、2つのラッパー関数を書くことだけを検討してください。それは顕著なオーバーヘッドを引き起こすべきではありません。コンパイラは、これらのラッパー関数を単一のジャンプ命令として記述することさえできます。 GCC(および互換)土地で

0

、あなたはまた、シンボルの可視性、バージョン管理やエイリアシングを制御するための属性の綿毛を使用することができます。

static void xxx_encrypt_decrypt(char *y, const char *x) { ... } 
void encrypt(char *, const char *) __attribute__((alias("xxx_encrypt_decrypt"))); 
void decrypt(char *, const char *) __attribute__((alias("xxx_encrypt_decrypt"))); 
関連する問題