6.8 汎用ポインタ
6.8.1 汎用型
ポインタを受け取る関数を作成する時、ポインタの型を特定させたくない場合があります。例えば、関数が状態に応じて異なる型のポインタを受け取ったり、または返すという構造が望まれる場合です。
例えば、型に関係なく、特定のメモリ範囲を指定した値で初期化するという関数を要求された場合、どのように関数を設計するべきでしょうか。方法のひとつとしては、char * 型のポインタを受け取り、これに指定された値を代入するという方法が考えられます。しかし、関数の利用者は char * 型以外の場合は関数を呼び出すたびにポインタをキャストする必要があります。
特定のメモリ範囲を初期化する行為に型は関係ないため、この関数はポインタ型に関係なくポインタを受け取るべきです。このような場合に汎用ポインタを利用します。汎用ポインタは任意のポインタを代入することが可能であり、同様に型キャストによって型を復元させることができます。汎用ポインタとはポインタの型に void キーワードが指定されたのポインタです。
void * 変数名
void 型のポインタは、あらゆる型のポインタをキャストして代入することができます。これを利用することで、より確実に、シンプルに、型に関係なくポインタを受けることができます。
#include <stdio.h> void FillMemory(void *mem , int size , char n) { int iCount; for(iCount = 0 ; iCount < size ; iCount++) *((char *)mem + iCount) = n; } int main() { unsigned int iCount , iArray[8]; FillMemory(iArray , 4 * 8 ,0xFF); for(iCount = 0 ; iCount < 8 ; iCount++) printf("iArray[%d] = %X\n" , iCount , iArray[iCount]); return 0; }
コード1の FillMemory() 関数は mem に初期化する領域へのポインタを、size は mem のサイズを、n は初期化する値を指定します。main() 関数では int 型の配列 iArray[8] を作成し、これを FillMemory() 関数を使って 0xFF で初期化しています。このプログラムは 32 ビットコンピュータを想定しているので、int 型は 4 バイト、配列は 8 要素まであるので iArray 配列変数は 32 バイトで構成されています。そのため、FillMemory() 関数の size 引数には 4 * 8 を指定しています。
このような、型に関係なく純粋にメモリアドレスを受け渡しすることが目的の関数を作ることは珍しいことではありません。拡張性の高いシステムを建築する時には、実体を抽象化する必要があるため void 型のポインタを応用することがあります。