線形リスト構造(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)