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