2012-03-04 4 views
4

Cでプログラミングすると、誤って間違ったポインタ型にvoid *をキャストするのを避けるために(あるいは少なくともその可能性を最小限に抑えるために)使用できる手法はありますか?私はいくつかの異なるタイプのCSVデータファイルを解析し、そのフィールドを特定のデータ構造に格納して処理するプログラムに取り組んでいます。たとえば、データファイルの1つのレコードはハッシュテーブルに格納されます。他のファイルからのデータは有向グラフに格納されます。誤ってvoid *を間違った型にキャストするのを避けるにはどうすればよいですか?

ファイルからフィールドのレコードを読み込み、フィールドをトークン化して適切なデータ型に格納する関数に各レコードを渡す1つのメイン解析関数を作成したいと考えています。ファイルタイプごとに別々の解析/トークン化関数を作成する代わりに、これを行うための汎用関数を作成したかったのです。私の設計では、呼び出し関数は、フィールドのレコード、データファイルに適用可能なトークナイザへの関数ポインタ、およびデータファイルに適用可能な宛先データ構造のノードを指すvoid *を渡します。

私が知りたいのは、誤ったトークナイザ/データ構造で誤って解析関数を呼び出さないようにする方法があるかどうかです。このような手法がない場合、このエラーをキャッチして重大な問題(例:sigfaults)を防ぐ効果的な例外処理メソッドがありますか?

できるだけポータブルなコードにしたいと思います。

どのような考えですか?私はこのアルゴリズムに結婚していない、もし誰かが私がそれに対してより良い考えを持っているならば。

void foo_generic(FieldRecords *records, Parser *parser, void *dest); 

... 

void foo_A(FieldRecords *records, A *dest) { foo_generic(records, &parse_A, dest); } 
void foo_B(FieldRecords *records, B *dest) { foo_generic(records, &parse_B, dest); } 
void foo_C(FieldRecords *records, C *dest) { foo_generic(records, &parse_C, dest); } 

今、タイプミスのために全ての電位がミスを簡単にする必要があり、単一の場所に制限されています

+2

構造体に型フィールドを前置きし、キャスト後にチェックしますか? –

+2

私は答えが「いいえ」であると確信しています。 void *を使用すると、自分でデータ型を追跡することを選択しています。 – Kevin

+2

'struct {unsigned short char type;}を作成できます。 void * data;} ' – Vyktor

答えて

5

一つの可能​​性は、離れて抽象型の安全性の問題は非常に薄いラッパー関数のセットを作成することです対称性によって見つけることができます。

あなたが特にいたずら感じているならば、あなたはこれらのラッパー関数の生成を簡素化するためにマクロを使用することができます。

#define FOO(T) void foo_##T(FieldRecords *records, T *dest) { \ 
        foo_generic(records, &parse_##T, dest); \ 
       } 

FOO(A) 
FOO(B) 
FOO(C) 

これは、タイプミスの可能性を最小限に抑えますが、デバッガ/ IDEを混乱の可能性が高くなり!

+0

ありがとう、これは素晴らしい解決策です。 – THV

関連する問題