情報処理・演習II --

情報処理・演習II
--- 第3回: ポインタ --情報科学科
井口幸洋
[email protected]
2015/9/30
情報処理・演習II
1
ポインタを学ぶにあたって
• ポインタで一番おちこぼれる
– 第3回~7回はポインタ ← 5回もやる.重要!
• なぜポインタを使うか?
– ポインタを使わないとできない計算
– ポインタを使うとコンパクトで効率のよい計算を実現
可能
2015/9/30
情報処理・演習II
2
本日の目標
• メモリとは?
• 変数とアドレスの関係について
• おまけ:
– 家での自習用にCの環境を自分のPCに作ろう
2015/9/30
情報処理・演習II
3
メモリ
• メモリに格納するもの
– データ
– プログラム
• メモリには番地がついている(住所と同じ)
– 1024個の格納場所があるメモリは0番地~1023番地
まである.これを指定するためには何ビット必要か?
答え:
[bits]
– 一つの番地には8[bits]格納できる. コンピュータに
よってこの値はかわる16[bits], 32[bits], 64[bits]のも
ある.
2015/9/30
情報処理・演習II
4
メモリの読み書き
CPU(Central Processing Unit)
Address
Dout
Din
10
8
8
Read
Write
2015/9/30
Memory
Address
Din
Dout
Read
Write
情報処理・演習II
5
メモリへの書き込み例(1):
65番地に3を書く
CPU(Central Processing Unit)
0001000001
Address
10
00000011
Dout
8
8
Din
Read 0
Write 0
最初Write=0にしておく
2015/9/30
情報処理・演習II
Memory
Address
Din
Dout
Read
Write
6
メモリへの書き込み例(2):
65番地に3を書く
CPU(Central Processing Unit)
0001000001
Address
10
00000011
Dout
8
8
Din
Read 0
Write 1
次に Write=1 にする
2015/9/30
情報処理・演習II
Memory
Address
Din
Dout
Read
Write
7
メモリへの書き込み例(3):
65番地に3を書く
CPU(Central Processing Unit)
0001000001
Address
10
00000011
Dout
8
8
Din
Read 0
Write 1
次に Write=1 にする
2015/9/30
情報処理・演習II
Memory
Address
Din
Dout
メモリ内部の
65番地に3が
書き込まれた
Read
Write
8
メモリからの読み出し例(1):
65番地の内容を読み出す
CPU(Central Processing Unit)
0001000001
Address
アドレスを
セットし,
Read = 1
にする.
10
8
Dout
8
Din
Read 1
Write 0
2015/9/30
情報処理・演習II
Memory
Address
Din
Dout
Read
Write
9
メモリからの読み出し例(2):
65番地の内容を読み出す
CPU(Central Processing Unit)
0001000001
Address
10
8
Dout
8
Din
Read 1
Write 0
2015/9/30
情報処理・演習II
Memory
Address
Din
00000011
Dout
Read
Write
指定された
番地の中身
が読み出さ
れ,Doutに
出力.
10
メモリからの読み出し例(3):
65番地の内容を読み出す
CPU(Central Processing Unit)
0001000001
Address
CPUはDin
に入力され
た信号を読
みとればよ
い.
2015/9/30
10
8
Dout
8
Din
Read 1
Write 0
情報処理・演習II
Memory
Address
Din
00000011
Dout
Read
Write
11
変数とアドレス
例:
int x;
int y;
仮に変数xを格納する場所が320番地,
変数yを格納する場所が328番地とする.
1番地に8ビット格納可
実際にメモリの何番地に置かれるかは,
わからない. OSやコンパイラが決める.
同じプログラムでも実行するたびに違う
場所にあることもある.
y
x
320
2015/9/30
324
328
情報処理・演習II
332
336
12
注意
• 「変数がどこかのあるアドレスに格納されてい
る」
• 「そのアドレスを使って特定の変数を指定でき
る」
• 使っている変数がどこのアドレスに格納されたか
どうかはプログラムを書く上で意識する必要はな
い.
2015/9/30
情報処理・演習II
13
ポインタ
• ポインタ(pointer):指し示す?何を?
int *p, *q;
double *dptr;
中身には
番地を格納
p
q
dptr
int型をさす変数pとqができる(pとqは整数変数を指すポ
インタ型変数と呼ぶ.
double型をさす変数dptrができる.
2015/9/30
情報処理・演習II
14
アドレス演算子(&の秘密)
int *p;
int x;
仮定:変数xを格納する場所は320番地.
&演算子:その変数のアドレスを取り出す
p = &x;
x
320
2015/9/30
p
324
328
情報処理・演習II
332
336
15
アドレス演算子(&の秘密)
int *p;
int x;
仮定:変数xを格納する場所は320番地.
&演算子:その変数のアドレスを取り出す
p = &x;
x
p
320
320
2015/9/30
324
328
情報処理・演習II
332
336
16
アドレス演算子(&の秘密)
int *p;
int x;
x=100;
scanf("%d", &x);
仮定:変数xを格納する場所は320番地.
なぜ、関数scanfの引数にはxのアドレス
を渡すのか?
x
100
320
2015/9/30
324
328
情報処理・演習II
332
336
17
アドレス演算子(&の秘密)
キーボードから値を
読み込みそれを320
番地に格納しておい
てくれ!
x
p
100
320
320
2015/9/30
324
328
情報処理・演習II
332
336
18
アドレス演算子(&の秘密)
了解!
キーボードから250
を読み込みましたので
ご指定のアドレスに
これから入れます。
x
100
320
2015/9/30
324
328
情報処理・演習II
332
336
19
アドレス演算子(&の秘密)
Thank you.
入れました。
毎度、ごひいきに
ありがとうございました。
x
250
320
2015/9/30
324
328
情報処理・演習II
332
336
20
アドレス演算子(&の秘密) だめな例
scanf("%d", x);
これでわかるかなあ?
x
p
100
320
320
2015/9/30
324
328
情報処理・演習II
332
336
21
アドレス演算子(&の秘密) だめな例
100を渡されたけど、
このおやじわかってんの
か?
番地を渡せってんだよ!
x
p
100
320
320
2015/9/30
324
328
情報処理・演習II
332
336
22
ポインタを通した変数の操作(1)
int *p;
int x, y;
x = 100;
p = &x;
*p = 5;
y = *p + 1;
x
p
y
100
320
2015/9/30
324
328
情報処理・演習II
332
336
23
ポインタを通した変数の操作(2)
int *p;
int x, y;
x = 100;
p = &x;
*p = 5;
y = *p + 1;
x
p
y
320
100
320
2015/9/30
324
328
情報処理・演習II
332
336
24
ポインタを通した変数の操作(2)
int *p;
int x, y;
x = 100;
p = &x;
*p = 5;
y = *p + 1;
x
*pが式の左側にあるとき:
pの中身を読み出して、それを
番地とし、その番地に値を書き
こむものとする.
p
y
320
100
320
2015/9/30
324
328
情報処理・演習II
332
336
25
ポインタを通した変数の操作(3)
int *p;
int x, y;
x = 100;
p = &x;
*p = 5;
y = *p + 1;
x
*pが式の左側にあるとき:
pの中身を読み出して、それを
番地とし、その番地に値を書き
こむものとする.
この場合、320番地に5を書けと
いうことになる.
p
y
320
5
320
2015/9/30
324
328
情報処理・演習II
332
336
26
ポインタを通した変数の操作(4)
int *p;
int x, y;
x = 100;
p = &x;
*p = 5;
y = *p + 1;
x
*pが式の右側にあるとき:
pの中身をまず読み出して、それを
番地とし、その番地を読み出す.
この例では320番地を読み出す.
今回は読み出した値に1を加えてyに
格納.
5
320
2015/9/30
324
y
p
6
320
328
情報処理・演習II
332
336
27
ポインタを通した変数の操作(5)
教科書を見ないで中身を埋めなさい
x
y
19
41
320
324
328
p
p = &x;
332
336
p
y
x
*p = *p + 100;
320
324
328
332
336
p
y
x
p = &y;
320
2015/9/30
324
328
332
情報処理・演習II
336
28
ポインタを通した変数の操作(6)
教科書を見ないで中身を埋めなさい
p
y
x
*p = *p + 100;
320
2015/9/30
324
328
332
情報処理・演習II
336
29
関数とポインタ
• 今までの例←ポインタ?役に立つの?
– scanf は一つの例. でも知らなくても使ってたし。。。。
• 今日は本節「関数とポインタ」の所でポインタの
応用を一つだけ学ぶ.
2015/9/30
情報処理・演習II
30
関数とポインタ
• 関数呼び出し時の値の受け渡し
– 「呼ぶほう」から引数を使って関数に値を渡せる.
– 関数の処理がわたったとき「呼んだ方に値を渡すの
はreturn文だけ」. 値が一つならいいけど、複数あっ
たらどうするの?
• ポインタの考え方を使えば複数の値も返せる.
2015/9/30
情報処理・演習II
31
例(関数とポインタ)
だめな例
やりたいこと: もらった値を2倍してかえしたい.
int main(void)
{
int a;
a = 3;
printf(“%d\n”,a);
twice(a);
printf(“%d\n”,a);
return(0);
}
2015/9/30
void twice(int x)
{
x = x * 2;
}
あれ、メインと関数の変数名
が違うからかなあ?
情報処理・演習II
32
例(関数とポインタ)
だめな例
やりたいこと: もらった値を2倍してかえしたい.
int main(void)
{
int a;
a = 3;
printf(“%d\n”,a);
twice(a);
printf(“%d\n”,a);
return(0);
}
2015/9/30
void twice(int a)
{
a = a * 2;
}
これでも駄目!
なぜ駄目なのか?
ヒント: main の変数a, 関数
twice内の変数aは同じ名前だけ
で違う場所にある.同姓同名み
たい。
情報処理・演習II
33
例(関数とポインタ)
良い例
やりたいこと: もらった値を2倍してかえしたい.番地をわたす!
int main(void)
{
int a;
a = 3;
printf(“%d\n”,a);
twice(&a);
printf(“%d\n”,a);
return(0);
}
2015/9/30
void twice(int *p)
{
*p = *p * 2;
}
関数twiceでは番地をもらいpに
いれる. その番地を使ってメイン
の変数aが格納されている所を
直接いじってしまう。
情報処理・演習II
34
課題1: ノーヒント
• printf を各所にいれて値を追跡せよ.
• この時、どうして値がそう変わったか?を図を使っ
て説明できるようにしなさい. これができないと定
期試験はできない.
2015/9/30
情報処理・演習II
35
課題2:3倍にするプログラム
• 本来はreturnで返すのがよいが、今回はポインタ
の勉強のため本節で述べた方法を使ってかきな
さい。
• twiceの例をもう1回理解してから、例をみないで
自分で書いてみなさい。
• 変数の箱を書いて図を描いて動作を説明できる
ようにしなさい(試験に出るかも).
2015/9/30
情報処理・演習II
36
課題3:値を交換する関数
main では
a = 5; b= 3;
swap(&a, &b)
printf(“a=%d, b=%d\n”,a,b);
この動作を完璧に
理解すること!
void swap(int *p, int*q)
{
int tmp;
tmp に p が指し示す値を代入;
p が指し示すところにqが指し示す値を代入;
qが指し示すところにtmpを代入;
}
2015/9/30
情報処理・演習II
37
課題4:二つの値を受け取り和と差を返す
main では
a = 5; b= 3;
watosa(&a, &b, &wa, &sa)
この動作を完璧に
理解すること!
void watosa(int *p, int*q, int *r, int *s)
{
}
2015/9/30
情報処理・演習II
38
自宅でC言語実行環境を作成する
• フリーソフトの学習向けオリジナルC言語コンパ
イラ&実行環境「C machine」 を導入
• www.google.co.jp で検索すると出てきます。
2015/9/30
情報処理・演習II
39
ダウンロード
2015/9/30
情報処理・演習II
40
FTPでダウンロードを選択
2015/9/30
情報処理・演習II
41
「保存」を選択
C:にdownloadなどという名前のフォルダを
つくっておくとよい.
2015/9/30
情報処理・演習II
42
ファイルを保存
2015/9/30
情報処理・演習II
43
cmkt200.lzhを解凍
• 解凍すると cmkt200 という名のフォルダ内に
Cmachine というフォルダができる
• このCmachineフォルダを自分の好きなところに
移動しておく。例えばデスクトップに移動してもよ
い。
• bin内部のCmachine.exeをダブルクリックすると
開始. プログラムをかいて実行してみてください.
2015/9/30
情報処理・演習II
44
Cmachine実行例
2015/9/30
情報処理・演習II
45