メモリ上の番地アドレスから遡って、変数の値 を見ていったりするする 第10章 ポインタ 1 文字を変数に入れるための char 型 文字列は配列を使い、その最後には『\0』が終 了点として必ず付けられる コンピュータ内で文字と整数値は対応しており、 それは文字コードに則って決められている 第10章 ポインタ 2 アドレスとポインタ 変数のアドレスとポインタ変数 ポインタと関数 ポインタと配列 第10章 ポインタ 3 すべての変数は、メモリ上にその分の領域とい うものが確保されている そのメモリ上の位置、番地のことをアドレスと いう ある変数のアドレスは、その変数名に『&』を 付け加えたもので、たとえば、変数a のアドレ スは『&a』と表される 第10章 ポインタ 4 このアドレスを代入できる特殊な変数をポイン タという 宣言 初期化 int *p; p = &a; 代入時は『*』がいらないので注意 第10章 ポインタ 5 また以下のようにポインタ変数に『*』をつけ ると、ポインタに入っているアドレスの指す変 数と同じ扱いになる 色々省略 int a = 25; int *p; 宣言時の『*』とは別個に p = &a; 思って *p = 50; printf(“%d\n”, a); つまり *p = a 第10章 ポインタ 6 ここでひとつ実行してみよう #include <stdio.h> int main(){ int a = 25; int *p = &a; printf(“%d\n”, printf(“%d\n”, *p = 50; printf(“%d\n”, printf(“%d\n”, return 0; } a); *p); *p); a); 第10章 ポインタ 7 実行結果 このように『*p』など『*』などをつけてアド レス先の変数と同じ扱いになることを 間接参照というよ 用語は好きに覚えてね 第10章 ポインタ 8 以下のコードを必ず使って、入力した数値を間 接参照で表示し、値を10倍して今度は元の変数 で表示をやってみよう printf(“a > %d\n”, *p); printf(“a × 10 = %d\n”, num); 実行例はこちら 第10章 ポインタ 9 ちょっと #include <stdio.h> まわりく int main(){ int num; どいかな int *p; printf("値を入力してください > "); scanf("%d", &num); p = # printf("num > %d\n", *p); *p *= 10; printf("num × 10 = %d\n", num); return 0; } 第10章 ポインタ 10 以下のプログラムは sub 関数で変数a の値を変 更しているが、うまくいっていない #include <stdio.h> void sub(int a){ a = 100; } int main(){ int a = 0; sub(a); printf(“%d\n”, a); return 0; } 第10章 ポインタ 11 関数に渡した値は、関数内の変数にコピーされ、 使用されている つまりその変数はローカル変数(そういやそんな のあった)なので、値を変更しても、関数の外ま でそれが適用されない ゆえに、前ページのプログラムの値は変わらな い 第10章 ポインタ 12 今度は関数にアドレスを渡してみる #include <stdio.h> void sub(int *p){ *p = 100; } int main(){ int a = 0; sub(&a); printf(“%d\n”, a); return 0; } 第10章 ポインタ 13 ポインタに『*』をつけたものは、そのアドレ スが指す変数と同じに扱う(2度目) この場合、アドレスを経由して変数の値をい じったため、関数の外においても変更が適用さ れているよ 第10章 ポインタ 14 半径を入力して、そこから円の円周と面積を求 める calc 関数を作ってみよう その時必ず以下の main 関数を用いてね int main(){ double a, b, c; printf(“半径は > ”); scanf(“%lf”, &a); calc(a, &b, &c); printf(“円周は > %f\n”, b); printf(“面積は > %f\n”, c); return 0; } 円周率は 3.14 で 第10章 ポインタ 15 『*』ば #include <stdio.h> かりで void calc(double a,double *b, double *c){ *b = a * 2 * 3.14; すね *c = a * a * 3.14; } int main(){ double a, b, c; printf(“半径は > ”); scanf("%lf", &a); calc(a,&b,&c); printf("円周は > %f\n",b); printf("面積は > %f\n",c); return 0; } 第10章 ポインタ 16 配列のアドレス たとえば int num[5]; という配列をつくったとして、それぞれの変数のアドレ スは &num[0], &num[1], &num[2], ……… となるのはイメージしやすいと思うけど、実は配列名で ある num も &num[0] と同じく num[0] のアドレス を表している 第10章 ポインタ 17 配列名 num が &num[0] と表すとき、 num+1 は &num[1]、num+2 は &num[2]… を表すことになる つまり ⇒ *num == num[0] *(num+1) == num[1] *(num+2) == num[2] ちなみに『*p』も『*(p+1)』『*(p+2)』…と していくことで、隣の領域にある変数の値を示 していくことができる 第10章 ポインタ 18 これで関数に配列を渡すやり方が説明できる! #include <stdio.h> void clear(int *p){ 実行してみよう! for(int i=0; i < 5; i++){ *(p + i) = 0; } } int main(){ int num[5] = {98, 102, 5, 77, 236}; clear(num); for(int i=0; i < 5; i++){ printf(“%d\n”, num[i]); } return 0; } 第10章 ポインタ 19 実行結果 clear 関数に配列名 num を引数として渡し、そ れをポインタで受け取る 関数内の処理で『*p』『*(p+1)』『*(p+2)』 …としていくことで『*num[0]』 『*num[1]』『*num[2]』…と同じことをし ているよ 第10章 ポインタ 20 変数のアドレスを格納できるポインタ変数 ポインタに『*』をつけることでアドレス先の 変数と同じ扱いができる 配列名は配列の先頭の変数のアドレスと同じ 配列を関数に渡す時、ポインタとして受けるこ とができる ややこしいのでまとめてみました 第10章 ポインタ 21 ヒント:文字列は『\0』 で必ず終わるよ 文字列を入力させて、その長さを算出する strlen 関数を使ったプログラムを作ってみよう main 関数はこんなカンジ int main(){ char words[128]; int num = 0; printf("文字列を入力してみよう > "); scanf("%s", words); num = strlen(words); printf("文字列の長さは %d です\n", num); return 0; } 第10章 ポインタ 22 #include <stdio.h> int strlen(char *p){ int n = 0; while(*p != '\0'){ p++; // このカタチでもポインタをずらせる n++; } return n; } int main(){ char words[128]; // ちゃんと十分に配列を確保しよう! int num = 0; printf(“文字列を入力してみよう > ”); scanf("%s", words); num = strlen(words); printf("文字列の長さは %d です\n", num); return 0; } 第10章 ポインタ 23 変数をまとめて宣言する方法 ヘッダーファイルを自分で作る プログラミングで便利な構造体のはなし 第10章 ポインタ 24 テンプレ 第10章 ポインタ 25
© Copyright 2024 ExpyDoc