LoginSignup
18
18

More than 5 years have passed since last update.

(void *)なキャストしたくない

Last updated at Posted at 2015-12-14

※ これはC言語の話です。

私はvoid *型関連のキャスト恐怖症で、void *なキャストを見ると恐怖で目がうるんでしまいます。

なんとかvoid *なキャストを明示的に書かないで済ませられないのでしょうか?

代入&引数渡し

void *型の変数に値を代入する場合、代入元がポインタ型であれば明示的なキャストは不要です。

なので…

int value;

void *pVoid = (void *)&value;

あああ、キャスト恐い!!

しかも不要なのに意味ありげな()で可読性が暴落ですよ(?)
大体1行に2回もvoid *って書かされてるのはDRYじゃない。

キャストは取っ払っちゃって、

int value;

void *pVoid = &value;

でいい。

タイプ数と横幅を節約できて幸せ!
プログラマの意図も、こっちの方が明確に過不足なく伝わります。

なので関数にパラメータを渡す場合も、

// void *を要求する関数
int requireVoidPointer( void *pVoid );

// 呼び出し
// (void *)&valueにする必要なし
int value;
requireVoidPointer( &value );

これでよし。

よかった、キャスト見ずに済みました…

コールバック関数のパラメータ

コールバック関数を受け取る関数は、以下のパラメータを持たせるパターンが多いですよね。
* コールバックの関数ポインタ
* コールバックを呼び出す際に渡すvoid *型の変数

こうすることによって、コールバックを受け取る関数をより汎用的に使えます。

// コールバック受け取る関数
int requireCallBack( void (* pCallBack)(void *pVoid), void *pParam )
{
  pCallBack( pParam );
}

こういった関数を使用する場合、コールバックとして渡される関数のパラメータはvoid *型である必要はありません!(ポインタ型であればよい)

なので、以下のようなコードを見ると辛い。

// コールバック受け取る関数
int requireCallBack( void (* pCallBack)(void *pVoid), void *pParam );

void main( void )
{
  int value = 10;

  // コールバック受け取る関数呼び出し
  requireCallBack( addThreeCBR, &value );
}

// コールバック用の関数
void addThreeCBR( void *pVoid )
{
  // わぁ、なんか変なキャスト
  int *pValue = (int *)pVoid;
  *pValue += 3;
}

ああ、なんでこんな目に…
どこかで設計ミスったの?

このaddThreeCBR()は、パラメータとしてint *型の変数を受け取らないとちゃんと動作しません。

それなのに関数の型が、requireCallBack()のプロトタイプに引きずられてint addThreeCBR( void *pVoid )になってしまっています。だから関数の内部で無駄なキャストが必要になってしまう。

実は、requireCallBack()に渡すコールバック関数の型がvoid (* pCallBack)(void *pVoid)だからって、本当に渡すコールバック関数のパラメータをvoid *にする必要はありません。代入の時と同じで、ポインタ型でさえあればいいんです。

もう思い切って、addThreeCBR()のパラメータをint *型にしちゃいましょう!

// パラメータをvoid *ではなくint *に変更
void addThreeCBR( int *pValue )
{
  *pValue += 3;
}

ああ、まがまがしいキャストと無駄なローカル変数が消せてすっきり!

18
18
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
18
18