![]() |
|||||||||||||||||||||||||||||||||||||||||||||||||||||
(1)考え方 CやC++では,calloc関数,free関数を使って, 領域の確保・開放を行い, ポインタでデータを参照することがよく行われますが, C#では,安全なプログラミングの観点から ポインタの使用は推奨されていません。 したがって,次のように あえてUnsafeを指定することになっています。 unsafe { char* p=stackalloc char[256]; for (int i=0; i<256;i++) *(p+i)=(char)i; int* values = stackalloc int[20]; int* a= & values[1]; int* b= & values[15]; MessageBox.Show (string.Format(" a - b = {0} \n b - a = {1}",a-b,b-a)); } しかし,リスト構造等を扱うとき,頻繁にデータ確保,開放 を行う必要があります。 一方,バグが潜む多くは,領域確保・開放の部分です。 ですから,領域確保・開放をシステム任せにしないで, 自分が制御できる範囲内で領域確保・開放を行いたいものです。 このようなとき,配列領域を分割して,動的に管理します。
(2)初期化 最初,次のように各要素のリストを作っておきます。 ![]() [プログラム処理](空ポインタを-1とする) public struct ElementData { public long 番号; public string 氏名; public int 点数; } public struct ElementSet { public ElementData Element; public long Next; } public ElementSet[] DataArea = new ElementSet[500]; public long ErasedP; // 未使用領域の先頭領域 private void 初期化( ) { for(int i=0;i<DataArea.Length-1;i++) DataArea[i].Next=i+1; DataArea[DataArea.Length-1].Next=-1; ErasedP=0; }
(3)領域の確保 最初,次のように各要素のリストを作っておきます。 未使用ポインタが指している要素を使うものとします。 すなわち,以下の手順で処理します。 @)未使用ポインタを関数値とする A)未使用ポインタが指しているポインタを未使用ポインタとする。 ![]() [プログラム例] private long GetArea( ) { long R = ErasedP; ErasedP = DataArea[ErasedP].Next; return R; }
(4)領域の返却 領域の返却とは,指定された要素を未使用領域の管理下に 戻すことです。すなわち, @)未使用ポインタの内容を返却領域のポインタとする。 A)未使用ポインタを返却領域へのポインタとする。 の手順で行います。 ![]() [プログラム例] private void FreeArea(long P) { if(P<0) return; DataArea[P].Next=ErasedP; ErasedP = P; } すでに,未使用要素であるような領域を返却すると, 未使用のリストが網状になってしまい, 未使用・使用の関係がメチャメチャになり 悲惨なことになることが多くあります。 したがってデバッグ時には, 以下のように返却されようとする要素が, 未使用領域でないかどうかを判定する処理を追加して テストを行うことが多いようです。 [デバッグ時のプログラム例] private void FreeArea(long P) { if(P<0) return; // ***以下,チェック用*** long PP = ErasedP; while(PP>=0) { if(PP==P) { MessageBox.Show("領域"+P.ToString() +"はフリーエリアです"); return; } PP=next(PP); } // ****チェックここまで*** DataArea[P].Next=ErasedP; ErasedP = P; }
![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() ![]() 上のタイトルをクリックします |
|||||||||||||||||||||||||||||||||||||||||||||||||||||