- ベストアンサー
ポインタと動的確保について
#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の内容が変わらない 理由がわかりません。 よろしくお願いします
- みんなの回答 (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と表示 } --------------------------------------------------
その他の回答 (1)
- asuncion
- ベストアンサー率33% (2127/6289)
下記のコードを実行してみると、*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; } (注)インデントのため、全角空白を使っています。
お礼
参照先が違ったんですね、納得できました。