WisdomSoft - for your serial experiences.

6.8 汎用ポインタ

任意のポインタを格納できる void 型ポインタを紹介します。void 型のポインタは関数などを通して型とは無関係にポインタを受け渡ししたい場合に応用できます。

6.8.1 汎用型

ポインタを受け取る関数を作成する時、ポインタの型を特定させたくない場合があります。例えば、関数が状態に応じて異なる型のポインタを受け取ったり、または返すという構造が望まれる場合です。

例えば、型に関係なく、特定のメモリ範囲を指定した値で初期化するという関数を要求された場合、どのように関数を設計するべきでしょうか。方法のひとつとしては、char * 型のポインタを受け取り、これに指定された値を代入するという方法が考えられます。しかし、関数の利用者は char * 型以外の場合は関数を呼び出すたびにポインタをキャストする必要があります。

特定のメモリ範囲を初期化する行為に型は関係ないため、この関数はポインタ型に関係なくポインタを受け取るべきです。このような場合に汎用ポインタを利用します。汎用ポインタは任意のポインタを代入することが可能であり、同様に型キャストによって型を復元させることができます。汎用ポインタとはポインタの型に void キーワードが指定されたのポインタです。

void 型のポインタ宣言
void * 変数名

void 型のポインタは、あらゆる型のポインタをキャストして代入することができます。これを利用することで、より確実に、シンプルに、型に関係なくポインタを受けることができます。

コード1
#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 実行結果

コード1の FillMemory() 関数は mem に初期化する領域へのポインタを、size は mem のサイズを、n は初期化する値を指定します。main() 関数では int 型の配列 iArray[8] を作成し、これを FillMemory() 関数を使って 0xFF で初期化しています。このプログラムは 32 ビットコンピュータを想定しているので、int 型は 4 バイト、配列は 8 要素まであるので iArray 配列変数は 32 バイトで構成されています。そのため、FillMemory() 関数の size 引数には 4 * 8 を指定しています。

このような、型に関係なく純粋にメモリアドレスを受け渡しすることが目的の関数を作ることは珍しいことではありません。拡張性の高いシステムを建築する時には、実体を抽象化する必要があるため void 型のポインタを応用することがあります。