• ベストアンサー

ポインタと動的確保について

#include <stdio.h> #include <stdlib.h> typedef struct LIST{ int number; char name[30]; }list; void test(list** ls) { list *tmp; tmp=*ls; //tmpに*lsのアドレスを参照させる printf("%d\n",(*ls)->number); //5と表示 printf("%d\n",tmp->number); //5と表示 (*ls)->number=10; //lsの指すものを10に変更 printf("%d\n",(*ls)->number); //10と表示 printf("%d\n",tmp->number); //10と表示 *ls=(list *)calloc(1,sizeof(list)); //lsを動的確保 printf("%d\n",(*ls)->number); //callocで初期化されるので0 printf("%d\n",tmp->number); //10と表示 ← なぜ指すもののlsの値が変わったの //に値が変わらないのか } int main(void) { char input[12]; list *ls,ls2; ls2.number=5; ls=&ls2; test(&ls); scanf("%s",input); return 0; } void test(list **)の内容の動的確保後にポインタ変数tmpが 刺しているはずの**lsの内容が変わったのにtmpの内容が変わらない 理由がわかりません。 よろしくお願いします

質問者が選んだベストアンサー

  • ベストアンサー
  • venzou
  • ベストアンサー率71% (311/435)
回答No.2

main関数と、test関数で同名の変数名を使っていますが、 紛らわしいので、main関数の方を下記の様に変更して説明します。 (説明のための変更です、実際に書き換える必要はありません。) list *ls1,ls2; -------------------------------------------------- test関数が呼ばれたとき、変数の状態は ls = &ls1 *ls == ls1 == &ls2 **ls == *ls1 == ls2 >tmp=*ls; //tmpに*lsのアドレスを参照させる この行ですが、コメントは間違いですね。 tmpに代入しているのは*lsです。つまりls2のアドレス。 ls1のアドレスではありません。 *ls == ls1 ですので、*ls を calloc() で更新しても、 tmpは変化しません。ls2のアドレスを指したままです。 コメント通りに代入するなら tmp = &(*ls) つまり、 tmp = ls です。 (tmpの宣言は list **tmp になります。) この代入後の変数の状態は tmp == ls == &ls1 *tmp == *ls == ls1 == &ls2 **tmp == **ls == *ls1 == ls2 >*ls=(list *)calloc(1,sizeof(list)); //lsを動的確保 この代入の後の変数の状態は tmp == ls == &ls1 *tmp == *ls == ls1 == (動的に確保されたlistのアドレス) **tmp == **ls == *ls1 == (動的に確保されたlist) 下記の様に書き直せば期待通りの動作になると思います。 -------------------------------------------------- void test(list** ls) { list **tmp; tmp=ls; //tmpに*lsのアドレスを参照させる printf("%d\n",(*ls)->number); //5と表示 printf("%d\n",(*tmp)->number); //5と表示 (*ls)->number=10; //lsの指すものを10に変更 printf("%d\n",(*ls)->number); //10と表示 printf("%d\n",(*tmp)->number); //10と表示 *ls=(list *)calloc(1,sizeof(list)); //lsを動的確保 printf("%d\n",(*ls)->number); //callocで初期化されるので0 printf("%d\n",(*tmp)->number); //0と表示 } --------------------------------------------------

JIF0131
質問者

お礼

参照先が違ったんですね、納得できました。

その他の回答 (1)

  • asuncion
  • ベストアンサー率33% (2127/6289)
回答No.1

下記のコードを実行してみると、*lsをcallocしたときに、 当初の*ls(つまりtmp)とはアドレスが異なっていることがわかります。 #include <stdio.h> #include <stdlib.h> typedef struct LIST {   int number;   char name[30]; } list; void test(list **ls) {   list *tmp;      tmp = *ls;              // tmpに*lsのアドレスを参照させる      printf("%p %p\n", tmp, *ls);      printf("%d\n", (*ls)->number);    // 5と表示   printf("%d\n", tmp->number);    // 5と表示      printf("%p %p\n", tmp, *ls);      (*ls)->number = 10;          // *lsの指すものを10に変更   printf("%d\n", (*ls)->number);    // 10と表示   printf("%d\n", tmp->number);    // 10と表示      *ls = (list *) calloc(1, sizeof(list));    // *lsを動的確保      printf("%p %p\n", tmp, *ls);    // *lsのアドレスは、当初とは異なる(※)      printf("%d\n", (*ls)->number);    // callocで初期化されるので0   printf("%d\n", tmp->number);    // 10と表示 ← なぜ指すもののlsの値が                     // 変わったのに値が変わらないのか } int main(void) {   list *ls, ls2;      ls2.number = 5;   ls = &ls2;   test(&ls);   return 0; } (注)インデントのため、全角空白を使っています。

関連するQ&A

専門家に質問してみよう