Download presentation
Presentation is loading. Please wait.
Published byBengt Eriksson Modified 約 5 年前
1
プログラミング論 ポインタ
2
見つかった誤り if( x = 3 ){ ... } "x=3"は比較ではなく、代入. x += 2 は、"xが2増える"が,
3
見つかった誤り x = x+1; はOK. x+1 = x; はNG. 代入は 右の値を左に入れる.
x = 3 はOKだが, 3 = x はNG.
4
見つかった誤り #define MAX 100 は,MAXを100に置き換えてからコンパイルする MAXという変数があるわけではない!
i=MAX; #define MAX 100 MAX=30; MAXという変数が あるわけではない i=100; これを コンパイル 100=30; これを コンパイル????
5
概要 前期最重要事項 : 関数 後期最重要事項 : pointer ポインタ ちなみに… 難易度が高いが,極めて重要
& と * の2種類しかない. ちなみに… 前期最重要事項 : 関数 後期最重要事項 : pointer 5
6
ポインタ なにかを「指す」ものがポインタである. C言語ではアドレスを理解すれば良い. 一般に理解が難しいとされる
7
メモリとアドレス 計算機はメモリにデータを保存している. 各バイトには,固有の通し番号(住所,アドレス)がついている.
通常1バイト(8bit)単位で管理される. 1バイトの「記憶領域=入れ物」が大量にある. 各バイトには,固有の通し番号(住所,アドレス)がついている. それぞれのメモリに 1バイトのデータを 記憶できる. 各1バイトに固有の 住所がついている. 0番地 1番地 2番地 3番地 4番地 5番地 6番地 7番地 8番地 9番地 7 100 56 23 53 45 95 2 65 1バイトの記憶領域=入れ物が10個ある例.
8
変数の記憶領域 変数を作ると,当然メモリ上にそのための記憶領域が自動的に確保される.
char abc; /* char型変数を1個用意 */ 変数abcの内容は, 4番地に記録する ことに決めたとする. (計算機が自動で行う) abc 0番地 1番地 2番地 3番地 4番地 5番地 6番地 7番地 8番地 9番地 7 100 56 23 53 45 95 2 65
9
変数の記憶領域 変数を作ると,当然メモリ上にそのための記憶領域が自動的に確保される.
char abc; /* char型変数を1個用意 */ char *p; abc = 7; p = &abc; &abc は,「変数abcは メモリの何番地か」を返す. pには「4番地」が入る. 7では無いことに注意! abc 0番地 1番地 2番地 3番地 4番地 5番地 6番地 7番地 8番地 9番地 7 100 56 23 7 45 95 2 65
10
&演算子 と *演算子 (重要!) &演算子は「変数のアドレス」を取得する演算子 *演算子は「メモリの中身」を取得する演算子
変数は,メモリのどこかに対応している &演算子は「変数のアドレス」を取得する演算子 使い方:変数名の前に&記号をつける 意味:その変数の位置、アドレス 例 p=&abc; /*変数pにアドレスを代入*/ *演算子は「メモリの中身」を取得する演算子 使い方:アドレス(アドレス変数)の前に*記号を付ける 意味:「そのアドレスのメモリ」の中身 例 x=*p; /*pにはアドレスが格納されているとする*/
11
&演算子 &演算子は変数のアドレスを調べる演算子. 変数の前に&を付けると,その変数アドレスが得られる. void main(){
char abc; char *p; p = &abc; printf("abcのアドレスは%pです.\n", p); } 実行結果 abcのアドレスは0013FF7Cです.
12
&演算子 void main(){ char abc, def; char *p; p = &abc;
printf("abcのアドレスは%pです.\n", p); p = &def; printf("defのアドレスは%pです.\n", p); } 実行結果 abcのアドレスは0013FF7Cです. defのアドレスは0013FF78です.
13
&演算子 void main(){ char abc, def, ghi; printf("アドレスは%p %p %pです.\n",
} 実行結果 アドレスは0013FF7C 0013FF FF74です.
14
&演算子 void main(){ char abc[5]; printf("アドレスは%p %p\n%p %p %pです.\n",
&(abc[0]), &(abc[1]), &(abc[2]), &(abc[3]), &(abc[4])); } 実行結果 アドレスは0013FF FF79 0013FF7A 0013FF7B 0013FF7Cです.
15
&演算子 void main(){ int abc[5]; printf("アドレスは%p %p\n%p %p %pです.\n",
&(abc[0]), &(abc[1]), &(abc[2]), &(abc[3]), &(abc[4])); } int型は4バイト 実行結果 アドレスは0013FF6C 0013FF70 0013FF FF FF7Cです.
16
アドレス型変数(ポインタ変数) アドレスを格納する変数 char ch; /* char型を格納する */
整数を格納できる変数があるように, アドレスを格納する変数がある. char ch; /* char型を格納する */ char *p; /* char型変数のアドレスを格納 */ p = &ch; /* ch は"4番地"なので,pには"4番地"が入る ch 0番地 1番地 2番地 3番地 4番地 5番地 6番地 7番地 8番地 9番地 7 100 56 23 7 45 95 2 65
17
ポインタ(アドレス型)をprintfで表示するには,
アドレス型変数(ポインタ変数) アドレスを格納する変数 整数を格納できる変数があるように, アドレスを格納する変数がある. char ch; /* char型を格納する */ char *p; /* char型変数のアドレスを格納 */ p = &ch; printf("アドレスは%pです\n", p); ポインタ(アドレス型)をprintfで表示するには, %p を使う.
18
*演算子 アドレスの間接参照演算子. アドレスの中身にアクセスする. char a, b; char *p; p b a
変数a,b,pを宣言した. それぞれ,メモリの 6番地,5番地,4番地が 割与えられたとする. a,bは「整数(char型の値)」を入れる入れ物. pは「アドレス」を入れる入れ物. 注意:実際はアドレスは1バイトではない. アドレスの間接参照演算子. アドレスの中身にアクセスする. char a, b; char *p; p b a 0番地 1番地 2番地 3番地 4番地 5番地 6番地 7番地 8番地 9番地
19
*演算子 アドレスの間接参照演算子. アドレスの中身にアクセスする. char a, b; char *p; a = 53;
つまり,メモリの6番地に 53を格納. p b a 0番地 1番地 2番地 3番地 4番地 5番地 6番地 7番地 8番地 9番地 53
20
*演算子 アドレスの間接参照演算子. アドレスの中身にアクセスする. char a, b; char *p; a = 53; p = &a;
&aで変数aのアドレスを得る. 変数aは6番地なので, pには6番地が代入される. 注意:実際は「番地」という 単位はつかない. p b a 0番地 1番地 2番地 3番地 4番地 5番地 6番地 7番地 8番地 9番地 6 番地 53
21
*演算子 アドレスの間接参照演算子. アドレスの中身にアクセスする. char a, b; char *p; a = 53; p = &a;
b = *p; アドレス(ポインタ)に * を付けると, そのアドレスの中身を 意味する. pは「6番地」. *pは「6番地の中身」 すなわち53 p b a 0番地 1番地 2番地 3番地 4番地 5番地 6番地 7番地 8番地 9番地 6 番地 53 53
22
aは「整数(char)」を入れる入れ物.
&演算子 と *演算子 (1) char a; char *p; aが5番地に, pが4番地に 割り当てられたとする. aは「整数(char)」を入れる入れ物. pは「アドレス」を入れる入れ物. p a 0番地 1番地 2番地 3番地 4番地 5番地 6番地 7番地 8番地 9番地
23
&演算子 と *演算子 (1) char a; char *p; p = &a; &a で, aのアドレスを獲得.
格納される. (メモリの4番地に "5番地"が格納される) p a 0番地 1番地 2番地 3番地 4番地 5番地 6番地 7番地 8番地 9番地 5 番地
24
&演算子 と *演算子 (1) char a; char *p; p = &a; a = 8; aに8を代入. aは5番地なので,
メモリの5番地に 8が格納される. p a 0番地 1番地 2番地 3番地 4番地 5番地 6番地 7番地 8番地 9番地 5 番地 8
25
&演算子 と *演算子 (1) char a; char *p; p = &a; a = 8; printf("%d", *p);
printf("%p", p); pは5番地. *pは「5番地の中身」. 5番地には, "8"が格納されているので, 8が表示される. 実質,a と *p は同一. 実行結果 8 p a 0番地 1番地 2番地 3番地 4番地 5番地 6番地 7番地 8番地 9番地 5 番地 8
26
&演算子 と *演算子 (2) char a; char *p; aが5番地に, pが4番地に 割り当てられたとする. p a 0番地
1番地 2番地 3番地 4番地 5番地 6番地 7番地 8番地 9番地
27
&演算子 と *演算子 (2) char a; char *p; p = &a; &a で, aのアドレスを獲得.
格納される. (メモリの4番地に "5番地"が格納される) p a 0番地 1番地 2番地 3番地 4番地 5番地 6番地 7番地 8番地 9番地 5 番地
28
&演算子 と *演算子 (2) char a; char *p; p = &a; *p = 8; pは5番地. *pは「5番地の中身」.
「5番地の中身」を "8"にする. 結果,aが"8"になる. p a 0番地 1番地 2番地 3番地 4番地 5番地 6番地 7番地 8番地 9番地 5 番地 8
29
&演算子 と *演算子 (2) char a; char *p; p = &a; *p = 8; printf("%d", a); 実行結果
当然,"8"が 表示される. 実質,「aへの代入」と 「*pへの代入」は 同一である. aへの値の代入は 行っていないが, aの値が変わる. char a; char *p; p = &a; *p = 8; printf("%d", a); 実行結果 8 p a 0番地 1番地 2番地 3番地 4番地 5番地 6番地 7番地 8番地 9番地 5 番地 8
30
&演算子 と *演算子 (3) char a; char *p; p = &a; a = 7; aに"7"を代入. すなわち,
メモリの5番地に "7"を格納. p a 0番地 1番地 2番地 3番地 4番地 5番地 6番地 7番地 8番地 9番地 5 番地 7
31
&演算子 と *演算子 (3) char a; char *p; p = &a; a = 7; *p = 8; pは「5番地」
「メモリ5番地を8にする」 aの値が変わってしまった. p a 0番地 1番地 2番地 3番地 4番地 5番地 6番地 7番地 8番地 9番地 5 番地 8
32
&演算子 と *演算子 (3) char a; char *p; p = &a; a = 7; *p = 8;
printf("%d", a); aの値を表示する. 当然,"8"が表示される. 実行結果 8 p a 0番地 1番地 2番地 3番地 4番地 5番地 6番地 7番地 8番地 9番地 5 番地 8
33
アドレス型変数(ポインタ変数) アドレスを格納する変数 整数を格納できる変数があるように, アドレスを格納する変数がある.
char ch; /* 整数や文字コードの入れ物 */ int i; /* 整数の入れ物 */ char *p0; /* char型変数のアドレスの入れ物 */ int *p1; /* int型変数のアドレスの入れ物 */
34
不慣れなうちは,この様な記述は避けるのが無難?
アドレス型変数(ポインタ変数) char a; /* a は char型 */ char *b; /* b は アドレス型 */ char c, *d, e, *f; /* cは char型,d はアドレス型, eは char型,f はアドレス型 */ char *g, h; /* g はアドレス型, hはchar型 */ 不慣れなうちは,この様な記述は避けるのが無難?
35
アドレス型変数(ポインタ変数) 変数の宣言 と 変数の使用 int i; 「int型」の変数iを作成.
int *p; 「int*」型の変数pを作成. p = &i; 作成済み変数pに値を代入. *p = 4; *pというメモリに4を代入.
36
練習0 void main(){ int i, *j, k; i = 3; j = &i; k = i; *j = 4; k = 5;
printf("i=%d\n", i); }
37
配列とアドレス(ポインタ) 配列の場合,アドレスは連続している. char ch[10]が100番地~109番地に割り振られた例.
101 番地 102 番地 103 番地 104 番地 105 番地 106 番地 107 番地 108 番地 109 番地
38
配列とアドレス(ポインタ) void main(){ char abc[5];
printf("アドレスは%p %p\n%p %p %pです.\n", &(abc[0]), &(abc[1]), &(abc[2]), &(abc[3]), &(abc[4])); } 実行結果 アドレスは0013FF FF79 0013FF7A 0013FF7B 0013FF7Cです.
39
配列とアドレス(ポインタ) void main(){ int abc[5];
printf("アドレスは%p %p\n%p %p %pです.\n", &(abc[0]), &(abc[1]), &(abc[2]), &(abc[3]), &(abc[4])); } 実行結果 アドレスは0013FF6C 0013FF70 0013FF FF FF7Cです.
40
配列とアドレス(ポインタ) 配列の場合,アドレスは連続している. int i[3]が100番地~111番地に割り振られた例
(この例では) int型は 4バイトである. i[0] i[1] i[2] 100 番地 101 番地 102 番地 103 番地 104 番地 105 番地 106 番地 107 番地 108 番地 109 番地 110 番地 111 番地
41
配列とアドレス(ポインタ) char ch[12]; char *p; 実行結果 0013FF74 p = &(ch[0]);
printf("%p\n", p); p = ch; 実行結果 0013FF74 添え字を付けずに ([0]などを付けずに) 配列名だけを書くと, 配列の先頭のアドレス を意味する. この場合,ch と &(ch[0]) は同義.
42
ポインタ演算 char ch[10]; char *p; p = ch; printf("%p\n", p); p++; 実行結果
0013FF74 0013FF75
43
ch[10]が100番地~109番地に割り当てられたとする.
配列とアドレス(ポインタ) char ch[10]; char *p; p = ch; pには, ch[10]の先頭アドレスである 100番地が代入される. ch[10]が100番地~109番地に割り当てられたとする. ch[0] ch[1] ch[2] ch[3] ch[4] ch[5] ch[6] ch[7] ch[8] ch[9] 100 番地 101 番地 102 番地 103 番地 104 番地 105 番地 106 番地 107 番地 108 番地 109 番地
44
配列とアドレス(ポインタ) char ch[10]; char *p; p = ch; *p = 1; pが100番地なので,
「100番地の内容」を "1"にする. つまり,ch[0]が "1"になる. ch[0] ch[1] ch[2] ch[3] ch[4] ch[5] ch[6] ch[7] ch[8] ch[9] 100 番地 101 番地 102 番地 103 番地 104 番地 105 番地 106 番地 107 番地 108 番地 109 番地 1
45
配列とアドレス(ポインタ) char ch[10]; char *p; p = ch; *p = 1; p++;
「101番地」になる. ch[0] ch[1] ch[2] ch[3] ch[4] ch[5] ch[6] ch[7] ch[8] ch[9] 100 番地 101 番地 102 番地 103 番地 104 番地 105 番地 106 番地 107 番地 108 番地 109 番地 1
46
配列とアドレス(ポインタ) char ch[10]; char *p; p = ch; *p = 1; p++; *p = 2;
101番地の中身が "2"になる. すなわちch[1]が ch[0] ch[1] ch[2] ch[3] ch[4] ch[5] ch[6] ch[7] ch[8] ch[9] 100 番地 101 番地 102 番地 103 番地 104 番地 105 番地 106 番地 107 番地 108 番地 109 番地 1 2
47
配列とアドレス(ポインタ) char ch[10]; char *p; p = ch; *p = 1; p++; *p = 2;
100 番地 101 番地 102 番地 103 番地 104 番地 105 番地 106 番地 107 番地 108 番地 109 番地 1 2
48
ポインタ演算 int i[10]; int *p; p = i; printf("%p\n", p); p++; 差が4 実行結果
0013FF74 0013FF78 差が4 i[0] i[1] i[2] 0013 FF74 番地 0013 FF75 番地 0013 FF76 番地 0013 FF77 番地 0013 FF78 番地 0013 FF79 番地 0013 FF7a 番地 0013 FF7b 番地 0013 FF7c 番地 0013 FF7d 番地 0013 FF7e 番地 0013 FF7f 番地
49
ポインタ演算 int型変数のアドレスに1足すと, 4バイト分増加して,次のintのアドレスになる. char型変数のアドレスを1足すと,
減算も同様. char型変数のアドレスを1足すと, 1バイト分増加して,次のcharのアドレスになる. ただし, int型が4バイトとは限らない. 処理系による.ほとんどの例で4バイト. char型は必ず1バイト.
50
ポインタ演算 p++を行うと, char *p; の場合,アドレスが1番地進む. int *p; の場合,アドレスが4番地進む.
double *p の場合,アドレスが8番地進む. (ただし,int型が4バイト,double型が8バイトの場合)
51
ポインタ演算 以下の様な操作が可能. 以下の様な操作は行えない.
アドレスに整数を加算/減算して,次の/前のアドレスに格納されているデータにアクセス. アドレス同士の引き算をし,何個離れているか調べる 以下の様な操作は行えない. アドレスに乗算/除算を行う. アドレス同士の加算.
52
ポインタ演算 (OK) char *p, *q; int i; の場合, p++; OK. pのアドレスが1番地増える.
p=q+2; OK. pはqの2番地後. p=q-2; OK. pはqの2番地前. i=p-q; OK. iにはpとqの差が代入される.
53
ポインタ演算 (NG) char *p, *q, *r; の場合, p=q+r; NG.アドレス同士の加算はNG.
p=q*2; NG.アドレスに乗算と除算はNG. p=q/2; NG.アドレスに乗算と除算はNG. p=q+1.2; NG.加算減算は整数のみ.
54
*演算子 と [] int *p; int x[10]; p = x; のとき p と &(x[0]) と x は同義.
55
*演算子 と [] int *p; int x[10]; p = x; のとき *p と x[0] と *x は同義.
56
練習1 void main(){ int i[2], *j; i[0]=3; i[1]=7; j=i; j++;
printf("%d\n", *j); }
57
練習2 void main(){ int i[2], *j; i[0]=3; i[1]=7; j=i; (*j)++;
printf("%d\n", *j); }
58
注意 int *p, x[10]; p = x; のとき p++; ←これはOK. x++; ←これはNG.
x は &(x[0]) という定数. よって,読めるが書けない.
59
関数の仮引数と実引数(値渡し) void func(int a){ a = 7; } void main(){ int x = 3;
func(x); printf("%d\n", x); x 100 番地 3
60
関数の仮引数と実引数(値渡し) void func(int a){ a = 7; } void main(){ int x = 3;
func(x); printf("%d\n", x); x 100 番地 3
61
関数の仮引数と実引数(値渡し) void func(int a){ a = 7; } void main(){ int x = 3;
func(x); printf("%d\n", x); x a 100 番地 104 番地 3 3 別のメモリに割り当てられた 別の変数
62
関数の仮引数と実引数(値渡し) void func(int a){ a = 7; } void main(){ int x = 3;
func(x); printf("%d\n", x); x a 100 番地 104 番地 3 7 別のメモリに割り当てられた 別の変数
63
関数の仮引数と実引数(値渡し) void func(int a){ a = 7; } void main(){ int x = 3;
func(x); printf("%d\n", x); x 100 番地 3 実行結果 3
64
関数の仮引数と実引数(値渡し) void func(int x){ x = 7; } void main(){ int x = 3;
この2個を 同じ名前にしても 結果は変わらない. void func(int x){ x = 7; } void main(){ int x = 3; func(x); printf("%d\n", x); x x 100 番地 104 番地 3 3 実行結果 別のメモリに割り当てられた 別の変数 3
65
関数の仮引数と実引数(参照渡し) void func(int *p){ *p = 7; } void main(){
int x = 3; int *px; px = &x; func(px); printf("%d\n", x); x px 100 番地 104 番地 3
66
関数の仮引数と実引数(参照渡し) void func(int *p){ *p = 7; } void main(){
int x = 3; int *px; px = &x; func(px); printf("%d\n", x); x px 100 番地 104 番地 3 100 番地
67
関数の仮引数と実引数(参照渡し) void func(int *p){ *p = 7; } void main(){
int x = 3; int *px; px = &x; func(px); printf("%d\n", x); x px 100 番地 104 番地 3 100 番地
68
関数の仮引数と実引数(参照渡し) void func(int *p){ *p = 7; } void main(){
int x = 3; int *px; px = &x; func(px); printf("%d\n", x); x px p 100 番地 104 番地 108 番地 3 100 番地 100 番地
69
関数の仮引数と実引数(参照渡し) void func(int *p){ *p = 7; } void main(){
int x = 3; int *px; px = &x; func(px); printf("%d\n", x); x px p 100 番地 104 番地 108 番地 7 100 番地 100 番地
70
関数の仮引数と実引数(参照渡し) void func(int *p){ *p = 7; } void main(){
int x = 3; int *px; px = &x; func(px); printf("%d\n", x); x px 100 番地 104 番地 7 100 番地 実行結果 7
71
応用例:値を2個返す関数 C言語では,戻り値は1個しか用意できない.
void sq_cu(int n, int *ps, int *pc){ *ps = n*n; *pc = n*n*n; } void main(){ int square, cube; sq_cu(3, &square, &cube); printf("%d %d\n", square, cube); squareが100番地, cubeが104番地で あったとする.
72
squareが100番地,cubeが104番地であったとする.
応用例:値を2個返す関数 C言語では,戻り値は1個しか用意できない. void sq_cu(int n, int *ps, int *pc){ *ps = n*n; *pc = n*n*n; } void main(){ int square, cube; sq_cu(3, &square, &cube); printf("%d %d\n", square, cube); 引数を 3,100番地,104番地 として,関数にジャンプ. squareが100番地,cubeが104番地であったとする.
73
squareが100番地,cubeが104番地であったとする.
応用例:値を2個返す関数 C言語では,戻り値は1個しか用意できない. void sq_cu(int n, int *ps, int *pc){ *ps = n*n; *pc = n*n*n; } void main(){ int square, cube; sq_cu(3, &square, &cube); printf("%d %d\n", square, cube); nが3, psが100番地, pcが104番地として 関数sq_cuを開始. squareが100番地,cubeが104番地であったとする.
74
squareが100番地,cubeが104番地であったとする.
応用例:値を2個返す関数 C言語では,戻り値は1個しか用意できない. void sq_cu(int n, int *ps, int *pc){ *ps = n*n; *pc = n*n*n; } void main(){ int square, cube; sq_cu(3, &square, &cube); printf("%d %d\n", square, cube); psは"100番地". 「100番地の中身を 3*3にする」 という処理. これにより squareの値が 変わる. squareが100番地,cubeが104番地であったとする.
75
squareが100番地,cubeが104番地であったとする.
応用例:値を2個返す関数 C言語では,戻り値は1個しか用意できない. void sq_cu(int n, int *ps, int *pc){ *ps = n*n; *pc = n*n*n; } void main(){ int square, cube; sq_cu(3, &square, &cube); printf("%d %d\n", square, cube); pcは"104番地". 「104番地の中身を 3*3*3にする」 という処理. これにより cubeの値が 変わる. squareが100番地,cubeが104番地であったとする.
76
squareが100番地,cubeが104番地であったとする.
応用例:値を2個返す関数 C言語では,戻り値は1個しか用意できない. void sq_cu(int n, int *ps, int *pc){ *ps = n*n; *pc = n*n*n; } void main(){ int square, cube; sq_cu(3, &square, &cube); printf("%d %d\n", square, cube); 実行結果 9 27 squareが100番地,cubeが104番地であったとする.
77
やってはいけないこと void main(){ int i=0, j[2]; j[0] = 7; j[1] = 8; /* OK! */
j[2] = 9; /* NG! */ printf("%d\n", i); } 実行結果 9 j[0] j[1] i 84 番地 85 番地 86 番地 87 番地 88 番地 89 番地 90 番地 91 番地 92 番地 93 番地 94 番地 95 番地 7 8 9
78
やってはいけないこと void main(){ int i[2], *p; p = i; /* OK. pはi[0]のアドレス */
*p = 7; /* OK. i[0] が 7 になる */ p++; /* OK. pはi[1]のアドレス */ *p = 8; /* OK. i[1] が 8 になる */ p++; /* NG.pはi[2]のアドレス? */ *p = 9; /* NG! i[2]相当の場所に 書き込みをしてしまう! */ }
79
ポインタへのポインタ int i; int *p; int **pp; iは int(整数)を入れる箱.
難しい! ポインタへのポインタ int i; int *p; int **pp; iは int(整数)を入れる箱. pは 「intの箱のアドレス」を入れる箱. ppは「『アドレスを入れる箱』のアドレス」を入れる箱. i p pp 84 番地 85 番地 86 番地 87 番地 88 番地 89 番地 90 番地 91 番地 92 番地 93 番地 94 番地 95 番地
80
ポインタへのポインタ int i; int *p; int **pp; i = 3; 難しい! i p pp 3 84 番地 85 番地
86 番地 87 番地 88 番地 89 番地 90 番地 91 番地 92 番地 93 番地 94 番地 95 番地 3
81
ポインタへのポインタ int i; int *p; int **pp; i = 3; p = &i; 難しい! i p pp 3 84番地
85 番地 86 番地 87 番地 88 番地 89 番地 90 番地 91 番地 92 番地 93 番地 94 番地 95 番地 3 84番地
82
ポインタへのポインタ int i; int *p; int **pp; i = 3; p = &i; pp = &p; 難しい! i p
84 番地 85 番地 86 番地 87 番地 88 番地 89 番地 90 番地 91 番地 92 番地 93 番地 94 番地 95 番地 3 84番地 88番地
83
ポインタへのポインタ int i; int *p; int **pp; i = 3; p = &i; 実行結果 pp = &p;
難しい! ポインタへのポインタ int i; int *p; int **pp; i = 3; p = &i; pp = &p; printf("%d\n", **pp); 実行結果 3 i p pp 84 番地 85 番地 86 番地 87 番地 88 番地 89 番地 90 番地 91 番地 92 番地 93 番地 94 番地 95 番地 3 84番地 88番地
84
ポインタへのポインタ int i, *p, **pp; i = 3; p = &i; pp = &p;
難しい! ポインタへのポインタ *ppは「88番地の中身」 なので, 「84番地」を意味する. *(*pp) は *(84番地) なので, 「84番地の中身」となり "3"を意味する. int i, *p, **pp; i = 3; p = &i; pp = &p; printf("%d\n", **pp); i p pp 84 番地 85 番地 86 番地 87 番地 88 番地 89 番地 90 番地 91 番地 92 番地 93 番地 94 番地 95 番地 3 84番地 88番地
85
多次元配列の配置 int a[3][2]は, 「長さ2の配列」が3本であって, 「長さ3の配列」が2本ではない?
86
復習 void main(){ int i=10, j=11; int *p; p=&j; printf("*p=%d\n",*p);
printf("i=%d j=%d",i,j); } 100 番地 104 番地 108 番地 10 11 104番地 の中身 10 11 10 11 104 10 11 104 10 7 104 10 7 104 104番地 の中身 *p=11 i=10 j=7 実行結果
87
練習 3 何と表示される? void main(){ int x=10, y=11, z=12; int *p;
printf("x=%d y=%d z=%d\n",x,y,z); p=&x; *p=5; p=&y; *p=6; p=&z; *p=7; }
88
練習 4 何と表示される? void main(){ int x[3]; int *p;
x[0]=10; x[1]=20; x[2]=30; printf("x[0]=%d x[1]=%d x[2]=%d\n",x[0],x[1],x[2]); p=x; /* p=&(x[0]) の意味 */ *p=7; p++; *p=6; *p=5; }
89
練習 5 何と表示される? void main(){ int x[3]; int *p;
x[0]=10; x[1]=20; x[2]=30; printf("x[0]=%d x[1]=%d x[2]=%d\n",x[0],x[1],x[2]); p=x; /* p=&(x[0]) の意味 */ *p=7; (*p)++; *p=6; }
Similar presentations
© 2024 slidesplayer.net Inc.
All rights reserved.