25
メモリ上の番地アドレスから遡って、変数の値 を見ていったりするする 10章 ポインタ 1

メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

  • Upload
    others

  • View
    4

  • Download
    0

Embed Size (px)

Citation preview

Page 1: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

メモリ上の番地アドレスから遡って、変数の値を見ていったりするする

第10章 ポインタ 1

Page 2: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

第10章 ポインタ 2

文字を変数に入れるための char 型

文字列は配列を使い、その最後には『¥0』が終了点として必ず付けられる

コンピュータ内で文字と整数値は対応しており、それは文字コードに則って決められている

Page 3: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

アドレスとポインタ 変数のアドレスとポインタ変数

ポインタと関数

ポインタと配列

第10章 ポインタ 3

Page 4: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

すべての変数は、メモリ上にその分の領域というものが確保されている

そのメモリ上の位置、番地のことをアドレスという

ある変数のアドレスは、その変数名に『&』を付け加えたもので、たとえば、変数a のアドレスは『&a』と表される

第10章 ポインタ 4

Page 5: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

このアドレスを代入できる特殊な変数をポインタという

宣言

初期化

代入時は『*』がいらないので注意

第10章 ポインタ 5

int *p;

p = &a;

Page 6: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

また以下のようにポインタ変数に『*』をつけると、ポインタに入っているアドレスの指す変数と同じ扱いになる

つまり *p = a

第10章 ポインタ 6

int a = 25; int *p; p = &a; *p = 50; printf(“%d¥n”, a);

色々省略

宣言時の『*』とは別個に 思って

Page 7: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

ここでひとつ実行してみよう

第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; }

Page 8: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

実行結果

このように『*p』など『*』などをつけてアドレス先の変数と同じ扱いになることを

間接参照というよ

用語は好きに覚えてね

第10章 ポインタ 8

Page 9: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

以下のコードを必ず使って、入力した数値を間接参照で表示し、値を10倍して今度は元の変数で表示をやってみよう

実行例はこちら

第10章 ポインタ 9

printf(“a > %d¥n”, *p); printf(“a × 10 = %d¥n”, num);

Page 10: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

ちょっとまわりくどいかな

第10章 ポインタ 10

#include <stdio.h> int main(){ int num; int *p; printf("値を入力してください > "); scanf("%d", &num); p = &num; printf("num > %d¥n", *p); *p *= 10; printf("num × 10 = %d¥n", num); return 0; }

Page 11: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

以下のプログラムは 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; }

Page 12: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

関数に渡した値は、関数内の変数にコピーされ、使用されている

つまりその変数はローカル変数(そういやそんなのあった)なので、値を変更しても、関数の外までそれが適用されない

ゆえに、前ページのプログラムの値は変わらない

第10章 ポインタ 12

Page 13: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

今度は関数にアドレスを渡してみる

第10章 ポインタ 13

#include <stdio.h> void sub(int *p){ *p = 100; } int main(){ int a = 0; sub(&a); printf(“%d¥n”, a); return 0; }

Page 14: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

ポインタに『*』をつけたものは、そのアドレスが指す変数と同じに扱う(2度目)

この場合、アドレスを経由して変数の値をいじったため、関数の外においても変更が適用されているよ

第10章 ポインタ 14

Page 15: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

半径を入力して、そこから円の円周と面積を求める 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 で

Page 16: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

『*』ばかりですね

第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; }

Page 17: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

配列のアドレス たとえば

という配列をつくったとして、それぞれの変数のアドレスは

&num[0], &num[1], &num[2], ………

となるのはイメージしやすいと思うけど、実は配列名である num も &num[0] と同じく num[0] のアドレスを表している

第10章 ポインタ 17

int num[5];

Page 18: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

配列名 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]

Page 19: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

これで関数に配列を渡すやり方が説明できる!

第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; }

実行してみよう!

Page 20: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

実行結果

clear 関数に配列名 num を引数として渡し、それをポインタで受け取る

関数内の処理で『*p』『*(p+1)』『*(p+2)』…としていくことで『*num[0]』『*num[1]』『*num[2]』…と同じことをし ているよ

第10章 ポインタ 20

Page 21: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

変数のアドレスを格納できるポインタ変数

ポインタに『*』をつけることでアドレス先の変数と同じ扱いができる

配列名は配列の先頭の変数のアドレスと同じ

配列を関数に渡す時、ポインタとして受けることができる

第10章 ポインタ 21

ややこしいのでまとめてみました

Page 22: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

文字列を入力させて、その長さを算出する 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』 で必ず終わるよ

Page 23: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

第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; }

Page 24: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

変数をまとめて宣言する方法

ヘッダーファイルを自分で作る

プログラミングで便利な構造体のはなし

第10章 ポインタ 24

Page 25: メモリ上の番地アドレスから遡って、変数の値 を見ていったり ...nanzanmmcwiki.net/_media/pc/lecture/c/2014/2014_10... · 2014-07-03 · 関数に渡した値は、関数内の変数にコピーされ、

テンプレ

第10章 ポインタ 25