汎用ポインタ(void *)とは
ポインタ(*)型でのみ使用できる、void型の変数のこと。
CやC++などの標準ライブラリで見られる。
汎用という単語の通り、あらゆるポインタ型に変換可能。ポインタ型であればどのような型でも受け取ることができる。
char型やint型と異なり対象のサイズがないので用途に応じてキャストして使う。
C 標準ライブラリでの使用例
1. memcpy
srcの先頭からlenバイト分をdestへコピーする関数。
引数のdestとsrcはvoid型であり、関数内でchar型にキャストされる。
memcpy.c
void *memcpy(void *dest, const void *src, size_t len)
{
char *d_cpy;
const char *s_cpy;
d_cpy = (char *)dest; //char*型にキャスト
s_cpy = (const char*)src; //const char*型にキャスト
while (len--)
*d_cpy++ = *s_cpy++;
return (dest);
}
2. memchr
srcの先頭からlenバイト分検索し、文字chがある位置のポインタを返す関数。
引数のsrcがconst void型であり、関数内でconst char型にキャストされる。
※const: 中身を書き換えられたくない値に対して書き込み禁止とする修飾子
memchr.c
void *memchr(const void *src, int ch, size_t len)
{
const char *src_cpy;
int count;
src_cpy = (const char *)src; //const char*型にキャスト
count = 0;
while (len--)
{
if (src_cpy[count] == ch)
return ((void *)&src_cpy[count]);
count++;
}
return (NULL);
}
C標準ライブラリのmem-関数では、メモリそのものを処理対象とするため、あらゆる型に対応できるよう汎用ポインタ(void *)型が用いられる。
その特性上、mem-関数は
- strcpy関数のように戻り値のポインタの終端にnull('¥0')を付与することはない(返すのは文字列ではなくメモリ領域だから)
- srcの途中にnull('¥0')が含まれていてもコピーや検索を中断しない。
#汎用ポインタ(void *)のメリット
- あらゆる型を出入力に使うことができる
- ポインタの参照先の型が見えないようにすることでメモリアクセスを制限する