C言語 メモ

 void型ポインタ(汎用ポインタ)  
  メモリへアクセスする型がわからないポインタを void型ポインタと云う。  汎用ポインタとも呼ばれる。
(メモリへアクセスする型が不明or未定のメモリ番地を管理するための変数を void型ポインタと云う。) 
  void * ptr  と記述される。

 ★ 汎用ポインタ(void *)のメリット
   ・ あらゆる型を出入力に使うことができる
   ・ ポインタの参照先の型が見えないようにすることでメモリアクセスを制限する

<使用例>
 
 
・ いろいろなポインタ型を代入する例
#include <stdio.h>

char	data1 = 'A';
int	data2 = 1234;
float	data3 = 3.141593;

void * pdata;	// void型ポインタ変数の宣言

int main()
{
	pdata = &data1;
	printf("pdata=%c\n", *((char*)pdata));	//(char*)でキャストして char型のポインタに変換

	pdata = &data2;
	printf("pdata=%d\n", *((int*)pdata));	//(int*)でキャストして int型のポインタに変換

	pdata = &data3;
	printf("pdata=%f\n", *((float*)pdata));//(float*)でキャストして float型のポインタに変換

	return 0;
}
 <実行結果>
pdata=A
pdata=1234
pdata=3.141593
 
   
 
・  関数の汎用化の例、(C言語の標準ライブラリ関数での使用)
   void*を使用することにより、データの型毎に関数を作成しなくてよくまとめて1つの関数で記述できる。
書式
void *memset(void *s, int c, size_t n);
引き数
s … メモリ領域のポインタ
c … メモリ領域に設定する文字
n … 文字cを設定するバイト数

戻り値
sのポインタ

解説
メモリ領域sの先頭からnバイトを文字cに設定する関数。

呼び出し形式
#include <mem.h> or
#include <string.h>
#include <stdio.h>
#include <mem.h>

int main()
{
	char data1;
	int  data2;
	char buf[16];
	void * ptr1;
	void * ptr2;
	void * ptr3;

	ptr1 = memset(&data1, 0x42, 2);	//汎用ポインタ(void *)にchar型のポインタを代入
	ptr2 = memset(&data2, 0x78, 3);	//汎用ポインタ(void *)にint型のポインタを代入

	memset(buf, '\0', 16);	//文字終端が\0となり、文字列となるようにbuf[0]~buf[15]に\0をセット
	memset(buf, 'B', 6);
	ptr3 =memset(buf, 'A', 2);

	printf("data1: 0x%x,\nptr1  =0x%p, \n&data1=0x%p\n\n", data1, ptr1, &data1);
	printf("data2: 0x%x,\nptr2  =0x%p, \n&data2=0x%p\n\n", data2, ptr2, &data2);
	printf("buf: %s, \nptr3=0x%p,\nbuf =0x%p,\n", buf, ptr3, buf);

	return 0;
}
<実行結果>
data1: 0x42,
ptr1 =0x000000000061FE07,
&data1=0x000000000061FE07

data2: 0x787878,
ptr2 =0x000000000061FE00,
&data2=0x000000000061FE00

buf: AABBBB,
ptr3=0x000000000061FDF0,
buf =0x000000000061FDF0,
 
   
 
・ ハンドルの型として使用する例 
  (void型ポインタを使って外部への型情報を隠蔽する)
//3 pVoid malloc.h


//ハンドルの型を void型ポインタに定義
typedef void * HANDLE;  //void型ポインタを使って外部への型情報を隠蔽する

//3 pVoid malloc.c

/*
ヘッダ 	stdlib.h
書式 	void *malloc(size_t size);
引数 	size … 動的に確保するメモリのサイズ(バイト単位)
戻り値 	成功:確保されたメモリのポインタ
失敗:NULL
解説 	システムのメモリからsizeバイトのメモリを確保してプログラムに割り当て、そのポインタを返す。
確保したメモリは不要になったらfree()関数で解放するように注意する。
また、malloc()で確保したメモリは初期化されていないので、memset()などを使用して初期化する必要がある。
*/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "3 pVoid malloc.h"

//個人情報管理用の構造体作成
typedef struct
{
    char            name[32];	//  登録氏名
    unsigned short	years;		//  年齢
}ACCOUNT;


HANDLE creatAccount(const char * name, unsigned short age)
{
    ACCOUNT * pAccount = NULL;

    // メモリ領域をヒープメモリに確保
    pAccount = (ACCOUNT *)malloc(sizeof(ACCOUNT)); //戻り値:確保したメモリの汎用ポインタ

    //  個人情報を初期化
    strcpy_s(pAccount->name, 32, name);
    pAccount->years = age;

    return pAccount;	//確保したメモリの汎用ポインタをハンドルに使う
}

int freeAccount(HANDLE handle)
{
	ACCOUNT *pAccount = (ACCOUNT *)handle;
	free(pAccount);		//メモリ解放

	return 0;
}


int printData(HANDLE handle)
{
	ACCOUNT * pAccount = (ACCOUNT *)handle;

	printf("-----------------------------\n");
	printf("Name:%s\n", pAccount->name);
	printf("Age:%u\n", pAccount->years);

	return 0;
}


int main()
{
	HANDLE handle1 = NULL;
	HANDLE handle2 = NULL;

	// 個人情報の作成
	handle1 = creatAccount("Yamada Taro", 27);
	handle2 = creatAccount("Yamada Hanako", 24);

	printData(handle1);		//プリント
	printData(handle2);

	freeAccount(handle1);	//メモリ解放
	freeAccount(handle2);

	return 0;
}



<実行結果>
-----------------------------
Name:Yamada Taro
Age:27
-----------------------------
Name:Yamada Hanako
Age:24
 
     
  ・ 構造体の中で 単なるメンバー変数として使用する例  
 
//4 pVoid mere member.c

#include <stdio.h>
#include <stdlib.h>

//個人情報管理用の構造体作成
typedef struct
{
    char            name[32];	//  登録氏名
    unsigned short	years;		//  年齢
}ACCOUNT;

typedef enum
{
	INIT,
	RUN,
	ERROR,
}APP_STATES;	//アプリケーションの状態

typedef struct
{
	APP_STATES state;	////アプリケーションの状態に係るメンバー
	void * ptr;			//汎用ポインタのメンバー
}APP_DATA;

APP_DATA appData;


int main()
{
	appData.ptr = (void *)malloc(sizeof(ACCOUNT));

	if(appData.ptr == NULL)	return -1;
	else
	{
		appData.state = RUN;
		printf("appData.ptr = 0x%p", appData.ptr);
	}

	return 0;
}


 
  <実行結果>  
  appData.ptr = 0x00000000007F6D50