線形リスト構造(1)
Copyright(C) 1July2008 coskx
TNCT
多くの同じ型の変数を扱う場合,配列が使われることが多い。プログラミングの時点で,使用する配列の大きさ(要素数)がわかっている場合は静的な配列を使う。
int
array[1024]; /*静的な配列の例*/
しかし,プログラミングの時点で配列の大きさがわからない場合は,配列の動的確保の手法があった。しかし,この方法でも,プログラムが起動した直後に配列の大きさが決まらなければ,配列を確保することができない。たとえば人の名前を登録する場合,何人で終わるか見当もつかないことがある。あらかじめ1000人ぐらいを予想してプログラム起動時に1000人分の配列を作っても,途中で不足してしまうこともある。
さて,このように,プログラムの実行が進むにつれて,保存すべきデータ量が増えてゆくときには線形リスト構造というデータ保存の形式がある。線形リスト構造では1データの登録時に1要素を確保するという手法をとる。しかも新たな要素が確保された(作られた)時には新しい要素のアドレスを,直前の要素が覚えているようにする。
このような機能を持つ要素は次のような構造体となる。(ここでは登録データ用の変数は1つだが,複数あってもよい)
線形リスト構造を作る構造体 |
構造体の要素1 |
登録データ用の変数 |
構造体の要素2 |
次のアドレスをしまうためのポインタ変数 |
|
1.線形リスト構造にカタカナ名前を3つならべて,表示する |
|
|
線形リスト構造に,「ハリー・ポッター」「ロン・ウィーズリー」「ハーマイオニー・グレンジャー」の3つのカタカナ名前を並べてみる。
線形リスト構造をつくる構造体は次のようになる。
名前の線形リスト構造を作る構造体
list_t |
構造体の要素1 |
登録データ用の文字列変数(char型配列) |
構造体の要素2 |
次のアドレスをしまうための「list_tを指すポインタ変数」 |
実用性はないが,線形リスト構造を理解しやすいサンプルプログラムを作る。
最初から3つのデータをの入った構造体を作り,それをリスト構造になるように連結する。
(1)初めの状態(リスト構造の元が並んでいるだけの状態)
元締めとなる「list_tを指すポインタ変数」
namelist |
値(アドレス) |
NULL(無効) |
list_t構造体 nodeA |
値(登録データ) |
「ハリー・ポッター」 |
値(次のアドレス) |
NULL(無効) | |
→ |
list_t構造体 nodeB |
値(登録データ) |
「ロン・ウィーズリー」 |
値(次のアドレス) |
NULL(無効) | |
→ |
list_t構造体 nodeC |
値(登録データ) |
「ハーマイオニー・グレンジャー」 |
値(次のアドレス) |
NULL(無効) | |
| | | | | | | |
(2)3つのデータが線形リスト構造に連結されたされた状態
元締めとなる「list_tを指すポインタ変数」
namelist |
値(アドレス) |
nodeAを指す |
list_t構造体 nodeA |
値(登録データ) |
「ハリー・ポッター」 |
値(次のアドレス) |
nodeBを指す | |
→ |
list_t構造体 nodeB |
値(登録データ) |
「ロン・ウィーズリー」 |
値(次のアドレス) |
nodeCを指す | |
→ |
list_t構造体 nodeC |
値(登録データ) |
「ハーマイオニー・グレンジャー」 |
値(次のアドレス) |
NULL(無効) | |
| | | | | | | |
このように,データ保存用の構造体は,データを格納する変数と,次の構造体のアドレスを保存するポインタ変数からできている。
構造体はこのポインタ変数によってつながっており,最後の構造体のポインタ変数には必ず「NULL」が入るようになっている。
サンプルプログラムを次に示す。登録の様子を見るために,データ未登録状態の様子,データを連結した後でどのようにリスト構造ができているかを見せます。この見せるからくりは,void
printListStructure(void)である。
List.1 線形リスト構造の紹介プログラム |
#include <stdio.h> #include
<stdlib.h> #include <string.h> #define debug
typedef struct list_type {
char name[32]; struct list_type *next; }
list_t;
list_t nodeA={"ハリー・ポッター", NULL}; list_t
nodeB={"ロン・ウィーズリー", NULL}; list_t nodeC={"ハーマイオニー・グレンジャー",
NULL};
list_t *namelist=NULL;
/*3つのデータをリスト構造になるように連結する関数*/ /*この関数はテスト用で汎用性はない*/ void
connect3Nodes(void) {
namelist=&nodeA;
nodeA.next=&nodeB;
nodeB.next=&nodeC; }
/*登録済データ数の読み出し*/ int
getNumber(void) { int
num=0; list_t *ptr=namelist;
while (ptr!=NULL) {
ptr=ptr->next;
num++; } return
num; }
/*登録済データの指定番号の文字列データの取り出し*/ /*buffはデータ取得の受け入れ場所*/ /*numberは指定番号 0から数えるが*/ void
getName(char *buff,int number) { int
i=0; list_t *ptr=namelist;
strcpy(buff,""); while (ptr!=NULL)
{ if (i==number)
{
strcpy(buff,ptr->name);
break; }
ptr=ptr->next;
i++; } }
void
printListStructure(void) { static
counter=0; list_t *node;
printf("** printListStructure (debug %d) **\n",++counter);
printf("&namelist(root)=%p\n",&namelist);
printf("namelist(root) =%p\n",namelist);
node=namelist; while (node!=NULL)
{ printf("&node =
%p\n",node);
printf(" node.name =
[%s]\n",node->name);
printf(" node.next =
[%p]\n",node->next);
node=node->next; }
printf("\n"); }
int main() { int
number,i; char tmp[128];
printListStructure(); connect3Nodes();
/*3つのデータをリスト構造になるように連結*/
printListStructure(); number=getNumber();
/*登録済データ数の取得*/
printf("%d\n",number); for (i=0;i<number;i++)
{ getName(tmp,i);
/*番号指定でデータの取得*/
puts(tmp); } return
0; } |
実行結果 |
&nodeA=0040C000 &nodeB=0040C024 &nodeC=0040C048 **
printListStructure (debug 1)
** &namelist(root)=0040D020 namelist(root) =00000000
** printListStructure (debug 2)
** &namelist(root)=0040D020 namelist(root)
=0040C000 &node = 0040C000 node.name =
[ハリー・ポッター] node.next = [0040C024] &node =
0040C024 node.name = [ロン・ウィーズリー] node.next
= [0040C048] &node = 0040C048 node.name =
[ハーマイオニー・グレンジャー] node.next =
[00000000]
3 ハリー・ポッター ロン・ウィーズリー ハーマイオニー・グレンジャー |
実行した結果,3つのデータが連結されリスト構造ができているのが次のようにわかる。
(1)データ未連結状態(** printListStructure (debug 1) **)
元締めとなるポインタ変数 namelist この変数のアドレス:0040D020 |
値(アドレス) |
NULL(表示では00000000) |
list_t構造体 nodeA この変数のアドレス:0040C000 |
値(登録データ) |
「ハリー・ポッター」 |
値(次のアドレス) |
NULL(無効) | |
→ |
list_t構造体 nodeB この変数のアドレス:0040C024 |
値(登録データ) |
「ロン・ウィーズリー」 |
値(次のアドレス) |
NULL(無効) | |
→ |
list_t構造体 nodeC この変数のアドレス:0040C048 |
値(登録データ) |
「ハーマイオニー・グレンジャー」 |
値(次のアドレス) |
NULL(無効) | |
(2)3つのデータが線形リスト構造に連結されたされた状態(** printListStructure (debug 2) **)
元締めとなる「list_tを指すポインタ変数」
namelist この変数のアドレス:0040D020 |
値(アドレス) |
0040C000 |
list_t構造体 nodeA この変数のアドレス:0040C000 |
値(登録データ) |
「ハリー・ポッター」 |
値(次のアドレス) |
0040C024 | |
→ |
list_t構造体 nodeB この変数のアドレス:0040C024 |
値(登録データ) |
「ロン・ウィーズリー」 |
値(次のアドレス) |
0040C048 | |
→ |
list_t構造体 nodeC この変数のアドレス:0040C048 |
値(登録データ) |
「ハーマイオニー・グレンジャー」 |
値(次のアドレス) |
NULL(表示では00000000) | |
|
2.線形リスト構造にカタカナ名前を登録し,表示後,全削除する例(1) (先頭にダミーデータを置いた実装) |
|
|
| | | | | | | |
「1」で示した例は,はじめから構造体にデータが埋め込んであり,実用的ではない。自由にデータを登録したり,削除したりできる必要がある。線形リスト構造にはいろいろな実装方法が考えられるが,簡単な方法としてよくつかわれるのが,線形リストの先頭にダミーデータ(見せかけの無意味データ)を1つ置く方法である。ここでは,先頭にダミーデータを最初から置いておく実装方法について説明する。
この方法はダミーデータを使うため,スマートでない。「3」にダミーデータを使わない方法を説明している。
線形リスト構造に,「ハリー・ポッター」「ロン・ウィーズリー」「ハーマイオニー・グレンジャー」の3つのカタカナ名前を順番に登録する。
登録用の線形リスト構造をつくる構造体は次のようになる。
名前の線形リスト構造を作る構造体
list_t |
構造体の要素1 |
登録データ用の文字列変数(char型配列) |
構造体の要素2 |
次のアドレスをしまうための「list_tを指すポインタ変数」 |
(1)何も登録されていない状態(ダミーデータのみ存在)
list_t構造体 ダミー |
値(登録データ) |
「dummy」 |
値(次のアドレス) |
NULL(無効) |
(2)1つ目のデータ(「ハリー・ポッター」)が登録された状態
list_t構造体 ダミー |
値(登録データ) |
「dummy」 |
値(次のアドレス) |
アドレスa | |
→ |
「アドレスa」に確保された 名前のないlist_t構造体 |
値(登録データ) |
「ハリー・ポッター」 |
値(次のアドレス) |
NULL(無効) | |
| |
(3)2つ目のデータ(「ロン・ウィーズリー」)が登録された状態
| | | |
list_t構造体 ダミー |
値(登録データ) |
「dummy」 |
値(次のアドレス) |
アドレスa | |
→ |
「アドレスa」に確保された 名前のないlist_t構造体 |
値(登録データ) |
「ハリー・ポッター」 |
値(次のアドレス) |
アドレスb | |
→ |
「アドレスb」に確保された 名前のないlist_t構造体 |
値(登録データ) |
「ロン・ウィーズリー」 |
値(次のアドレス) |
NULL(無効) | |
| | | |
(4)3つ目のデータ(「ハーマイオニー・グレンジャー」)が登録された状態
list_t構造体 ダミー |
値(登録データ) |
「dummy」 |
値(次のアドレス) |
アドレスa | |
→ |
「アドレスa」に確保された 名前のないlist_t構造体 |
値(登録データ) |
「ハリー・ポッター」 |
値(次のアドレス) |
アドレスb | |
→ |
「アドレスb」に確保された 名前のないlist_t構造体 |
値(登録データ) |
「ロン・ウィーズリー」 |
値(次のアドレス) |
アドレスc | |
→ |
「アドレスc」に確保された 名前のないlist_t構造体 |
値(登録データ) |
「ハーマイオニー・ グレンジャー」 |
値(次のアドレス) |
NULL(無効) | |
| | | | | | | | | | | | | | | | | | | | | | | |
このように,データ保存用の構造体は,データを格納する変数と,次の構造体が確保された時のアドレスを保存するポインタ変数からできている。
データが登録された構造体はこのポインタ変数によってつながっており,最後に登録された構造体のポインタ変数には必ず「NULL」が入るようになっている。
サンプルプログラムを次に示します。登録の様子を見るために,データ未登録状態の様子,データを登録するたびにどのようにリスト構造ができているかを見せます。この見せるからくりは,void
printListStructure(void)である。
List.2
ダミーデータを先頭に置いた線形リスト構造の実装例 |
#include <stdio.h> #include
<stdlib.h> #include <string.h> #define debug
typedef struct list_type {
char name[32]; struct list_type *next; }
list_t;
list_t namelist={
/*先頭のダミーデータは最初から作っておく*/
"dummy", NULL };
/*名前の登録*/ void registerName(char
*name) { list_t
*newptr,*ptr=&namelist; while
(ptr->next!=NULL) {
/*このループから脱出したらptrは最後の要素*/
ptr=ptr->next; }
newptr=(list_t *)malloc(sizeof(list_t));
strcpy(newptr->name,name);
newptr->next=NULL; ptr->next=newptr; #ifdef
debug printf("got [%p] and saved it next to
[%p]\n",newptr,ptr); #endif }
/*登録済データ数の読み出し*/ int
getNumber(void) { int
num=0; list_t
*ptr=namelist.next; while (ptr!=NULL)
{
ptr=ptr->next;
num++; } return
num; }
/*登録済データの指定番号の文字列データの取り出し*/ /*buffはデータ取得の受け入れ場所*/ /*numberは指定番号 0から数えるが,先頭のダミーデータは無視して数える*/ void
getName(char *buff,int number) { int
i=0; list_t
*ptr=namelist.next;
strcpy(buff,""); while (ptr!=NULL)
{ if (i==number)
{
strcpy(buff,ptr->name);
break; }
ptr=ptr->next;
i++; } }
/*List構造の解放*/ void
closeList(void) { list_t
*ptr=namelist.next,*ptr1;
namelist.next=NULL; while (ptr!=NULL)
{
ptr1=ptr;
ptr=ptr->next;
free(ptr1); #ifdef debug
printf("freed [%p]\n",ptr1); #endif
} }
/*リスト構造の利用開始*/ void
openList(void) { closeList(); }
#ifdef debug void
printListStructure(void) { static
counter=0; list_t *node;
printf("** printListStructure (debug %d)
**\n",++counter);
printf("&namelist(root)=%p\n",&namelist);
node=&namelist; while (node!=NULL)
{ printf("&node =
%p\n",node);
printf(" node.name =
[%s]\n",node->name);
printf(" node.next =
[%p]\n",node->next);
node=node->next; }
printf("\n"); } #endif
int main() { int
number,i; char tmp[128];
openList(); /*リスト構造の利用開始*/ #ifdef debug
printListStructure(); #endif
registerName("ハリー・ポッター"); /*名前の登録*/ #ifdef debug
printListStructure(); #endif
registerName("ロン・ウィーズリー"); /*名前の登録*/ #ifdef debug
printListStructure(); #endif
registerName("ハーマイオニー・グレンジャー"); /*名前の登録*/ #ifdef
debug
printListStructure(); #endif number=getNumber();
/*登録済データ数の取得*/
printf("%d\n",number); for (i=0;i<number;i++)
{ getName(tmp,i);
/*番号指定でデータの取得*/
puts(tmp); } closeList();
/*List構造の解放*/
number=getNumber(); printf("%d\n",number); #ifdef
debug
printListStructure(); #endif return
0; } |
実行結果 |
** printListStructure (debug 1)
** &namelist(root)=0040C000 &node = 0040C000
node.name = [dummy] node.next = [00000000]
got [00373148] and saved it next to
[0040C000] ** printListStructure (debug 2)
** &namelist(root)=0040C000 &node = 0040C000
node.name = [dummy] node.next = [00373148] &node =
00373148 node.name = [ハリー・ポッター] node.next
= [00000000]
got [00373178] and saved it next to
[00373148] ** printListStructure (debug 3)
** &namelist(root)=0040C000 &node = 0040C000
node.name = [dummy] node.next = [00373148] &node =
00373148 node.name = [ハリー・ポッター] node.next
= [00373178] &node = 00373178 node.name =
[ロン・ウィーズリー] node.next = [00000000]
got [003731A8] and saved it next to
[00373178] ** printListStructure (debug 4)
** &namelist(root)=0040C000 &node = 0040C000
node.name = [dummy] node.next = [00373148] &node =
00373148 node.name = [ハリー・ポッター] node.next
= [00373178] &node = 00373178 node.name =
[ロン・ウィーズリー] node.next = [003731A8] &node =
003731A8 node.name = [ハーマイオニー・グレンジャー]
node.next = [00000000]
3 ハリー・ポッター ロン・ウィーズリー ハーマイオニー・グレンジャー freed
[00373148] freed [00373178] freed [003731A8] 0 **
printListStructure (debug 5)
** &namelist(root)=0040C000 &node = 0040C000
node.name = [dummy] node.next =
[00000000] |
デバッグモードで実行した結果,3つのデータが登録されてゆく状態が次のようにわかる。
(1)データ未登録状態(** printListStructure (debug 1) **)
list_t構造体 ダミー この変数のアドレス:0040C000 |
値(登録データ) |
「dummy」 |
値(次のアドレス) |
NULL(表示では00000000) |
(2)1つ目のデータ(「ハリー・ポッター」)が登録された状態
list_t構造体 ダミー この変数のアドレス:0040C000 |
値(登録データ) |
「dummy」 |
値(次のアドレス) |
00373148 | |
→ |
00373148に確保された 名前のないlist_t構造体 |
値(登録データ) |
「ハリー・ポッター」 |
値(次のアドレス) |
NULL(表示では00000000) | |
| |
(3)2つ目のデータ(「ロン・ウィーズリー」)が登録された状態
| | | |
list_t構造体 ダミー この変数のアドレス:0040C000 |
値(登録データ) |
「dummy」 |
値(次のアドレス) |
00373148 | |
→ |
00373148に確保された 名前のないlist_t構造体 |
値(登録データ) |
「ハリー・ポッター」 |
値(次のアドレス) |
00373178 | |
→ |
00373178に確保された 名前のないlist_t構造体 |
値(登録データ) |
「ロン・ウィーズリー」 |
値(次のアドレス) |
NULL(表示では00000000) | |
| | | |
(4)3つ目のデータ(「ハーマイオニー・グレンジャー」)が登録された状態
list_t構造体 ダミー この変数のアドレス:0040C000 |
値(登録データ) |
「dummy」 |
値(次のアドレス) |
00373148 | |
→ |
00373148に確保された 名前のないlist_t構造体 |
値(登録データ) |
「ハリー・ポッター」 |
値(次のアドレス) |
00373178 | |
→ |
00373178に確保された 名前のないlist_t構造体 |
値(登録データ) |
「ロン・ウィーズリー」 |
値(次のアドレス) |
003731A8 | |
→ |
003731A8に確保された 名前のないlist_t構造体 |
値(登録データ) |
「ハーマイオニー・ グレンジャー」 |
値(次のアドレス) |
NULL(表示では00000000) | |
| | | | | | | | | | | | | | | | | | | | | | | |
|
3.線形リスト構造にカタカナ名前を登録し,表示後,全削除する例(2) (先頭にダミーデータを使わない実装) |
|
|
「2」の方法は先頭にダミーデータを使ったが,使わない実装方法を説明する。
線形リスト構造に,「ハリー・ポッター」「ロン・ウィーズリー」「ハーマイオニー・グレンジャー」の3つのカタカナ名前を順番に登録する。
登録用の線形リスト構造をつくる構造体は次のようになる。
名前の線形リスト構造を作る構造体
list_t |
構造体の要素1 |
登録データ用の文字列変数(char型配列) |
構造体の要素2 |
次のアドレスをしまうための「list_tを指すポインタ変数」 |
(1)初めの状態(データが1つも入っていない状態)
元締めとなる「list_tを指すポインタ変数」
namelist |
値(アドレス) |
NULL(無効) |
(2)1つ目のデータ(「ハリー・ポッター」)が登録された状態
元締めとなるポインタ変数 namelist |
値(アドレス) |
アドレスa | |
→ |
「アドレスa」に確保された名前のないlist_t構造体 |
値(登録データ) |
「ハリー・ポッター」 |
値(次のアドレス) |
NULL(無効) | |
(3)2つ目のデータ(「ロン・ウィーズリー」)が登録された状態
元締めとなるポインタ変数 namelist |
値(アドレス) |
アドレスa | |
→ |
「アドレスa」に確保された名前のないlist_t構造体 |
値(登録データ) |
「ハリー・ポッター」 |
値(次のアドレス) |
アドレスb | |
→ |
「アドレスb」に確保された名前のないlist_t構造体 |
値(登録データ) |
「ロン・ウィーズリー」 |
値(次のアドレス) |
NULL(無効) | |
| | | | | |
(4)3つ目のデータ(「ハーマイオニー・グレンジャー」)が登録された状態
元締めとなるポインタ変数 namelist |
値(アドレス) |
アドレスa | |
→ |
「アドレスa」に確保された名前のないlist_t構造体 |
値(登録データ) |
「ハリー・ポッター」 |
値(次のアドレス) |
アドレスb | |
→ |
「アドレスb」に確保された名前のないlist_t構造体 |
値(登録データ) |
「ロン・ウィーズリー」 |
値(次のアドレス) |
アドレスc | |
→ |
「アドレスc」に確保された名前のないlist_t構造体 |
値(登録データ) |
「ハーマイオニー・グレンジャー」 |
値(次のアドレス) |
NULL(無効) | |
サンプルプログラムを次に示す。登録の様子を見るために,データ未登録状態の様子,データを登録するたびにどのようにリスト構造ができているかを見せている。この見せるからくりは,void
printListStructure(void)である。
List.3
ダミーデータを先頭に使わない線形リスト構造の実装例 |
#include <stdio.h> #include
<stdlib.h> #include <string.h> #define debug
typedef struct list_type {
char name[32]; struct list_type *next; }
list_t;
list_t *namelist=NULL;
/*名前の登録*/ void registerName(char
*name) { list_t *newptr;
list_t *ptr=namelist; newptr=(list_t
*)malloc(sizeof(list_t));
strcpy(newptr->name,name);
newptr->next=NULL; if (ptr!=NULL) {
/*1つ以上のノードが存在する*/ while
(ptr->next!=NULL)
{
ptr=ptr->next;
}
ptr->next=newptr; #ifdef
debug printf("got [%p] and
saved it next to [%p]\n",newptr,ptr); #endif }
else { /*先頭に登録*/
namelist=newptr; #ifdef
debug printf("got [%p] and
saved it as the first node\n",newptr); #endif
} }
/*登録済データ数の読み出し*/ int
getNumber(void) { int
num=0; list_t *ptr=namelist;
while (ptr!=NULL) {
ptr=ptr->next;
num++; } return
num; }
/*登録済データの指定番号の文字列データの取り出し*/ /*buffはデータ取得の受け入れ場所*/ /*numberは指定番号 0から数える*/ void
getName(char *buff,int number) { int
i=0; list_t *ptr=namelist;
strcpy(buff,""); while (ptr!=NULL)
{ if (i==number)
{
strcpy(buff,ptr->name);
break; }
ptr=ptr->next;
i++; } }
/*List構造の解放*/ void
closeList(void) { list_t
*ptr=namelist,*ptr1; while (ptr!=NULL)
{
ptr1=ptr;
ptr=ptr->next;
free(ptr1); #ifdef debug
printf("freed [%p]\n",ptr1); #endif
} namelist=NULL; }
/*リスト構造の利用開始*/ void
openList(void) { closeList(); }
#ifdef debug void
printListStructure(void) { static
counter=0; list_t *node;
printf("** printListStructure (debug %d)
**\n",++counter);
printf("&namelist(root)=%p\n",&namelist);
printf("namelist(root) =%p\n",namelist);
node=namelist; while (node!=NULL)
{ printf("&node =
%p\n",node);
printf(" node.name =
[%s]\n",node->name);
printf(" node.next =
[%p]\n",node->next);
node=node->next; }
printf("\n"); } #endif
int main() { int
number,i; char tmp[128];
openList(); /*リスト構造の利用開始*/ #ifdef debug
printListStructure(); #endif
registerName("ハリー・ポッター"); /*名前の登録*/ #ifdef debug
printListStructure(); #endif
registerName("ロン・ウィーズリー"); /*名前の登録*/ #ifdef debug
printListStructure(); #endif
registerName("ハーマイオニー・グレンジャー"); /*名前の登録*/ #ifdef
debug
printListStructure(); #endif number=getNumber();
/*登録済データ数の取得*/
printf("%d\n",number); for (i=0;i<number;i++)
{ getName(tmp,i);
/*番号指定でデータの取得*/
puts(tmp); } closeList();
/*List構造の解放*/
number=getNumber(); printf("%d\n",number); #ifdef
debug
printListStructure(); #endif return
0; } |
実行結果 |
** printListStructure (debug 1)
** &namelist(root)=0040D020 namelist(root) =00000000
got [00373148] and saved it as the first
node ** printListStructure (debug 2)
** &namelist(root)=0040D020 namelist(root)
=00373148 &node = 00373148 node.name =
[ハリー・ポッター] node.next = [00000000]
got [00373178] and saved it next to
[00373148] ** printListStructure (debug 3)
** &namelist(root)=0040D020 namelist(root)
=00373148 &node = 00373148 node.name =
[ハリー・ポッター] node.next = [00373178] &node =
00373178 node.name = [ロン・ウィーズリー] node.next
= [00000000]
got [003731A8] and saved it next to
[00373178] ** printListStructure (debug 4)
** &namelist(root)=0040D020 namelist(root)
=00373148 &node = 00373148 node.name =
[ハリー・ポッター] node.next = [00373178] &node =
00373178 node.name = [ロン・ウィーズリー] node.next
= [003731A8] &node = 003731A8 node.name =
[ハーマイオニー・グレンジャー] node.next = [00000000]
3 ハリー・ポッター ロン・ウィーズリー ハーマイオニー・グレンジャー freed
[00373148] freed [00373178] freed [003731A8] 0 **
printListStructure (debug 5)
** &namelist(root)=0040D020 namelist(root)
=00000000 |
デバッグモードで実行した結果,3つのデータが登録されてゆく状態が次のようにわかる。
(1)データ未登録状態(** printListStructure (debug 1) **)
元締めとなるポインタ変数 namelist この変数のアドレス:0040D020 |
値(アドレス) |
NULL(表示では00000000) |
(2)「ハリー・ポッター」が登録された状態(** printListStructure (debug 2) **)
元締めとなるポインタ変数 namelist この変数のアドレス:0040D020 |
値(アドレス) |
00373148 | |
→ |
00373148に確保された 名前のないlist_t構造体 |
値(登録データ) |
「ハリー・ポッター」 |
値(次のアドレス) |
NULL(表示では00000000) | |
(3)「ロン・ウィーズリー」が登録された状態(** printListStructure (debug 3) **)
元締めとなるポインタ変数 namelist この変数のアドレス:0040D020 |
値(アドレス) |
00373148 | |
→ |
00373148に確保された 名前のないlist_t構造体 |
値(登録データ) |
「ハリー・ポッター」 |
値(次のアドレス) |
00373178 | |
→ |
00373178に確保された 名前のないlist_t構造体 |
値(登録データ) |
「ロン・ウィーズリー」 |
値(次のアドレス) |
NULL(表示では00000000) | |
(4)「ハーマイオニー・グレンジャー」が登録された状態(** printListStructure (debug 4) **)
元締めとなるポインタ変数 namelist この変数のアドレス:0040D020 |
値(アドレス) |
00373148 | |
→ |
00373148に確保された 名前のないlist_t構造体 |
値(登録データ) |
「ハリー・ポッター」 |
値(次のアドレス) |
00373178 | |
→ |
00373178に確保された 名前のないlist_t構造体 |
値(登録データ) |
「ロン・ウィーズリー」 |
値(次のアドレス) |
003731A8 | |
→ |
003731A8に確保された 名前のないlist_t構造体 |
値(登録データ) |
「ハーマイオニー・グレンジャー」 |
値(次のアドレス) |
NULL(表示では00000000) | |