解説#1 C言語
ポインタとアドレス
https://www.youtube.com/user/blinknetmonitoring
安藤類央
技術解説1 ポインタとアドレス
① はじめの15分を通して、そもそも、ポインタ型の変数がなぜあ
るのか、何に役立つのかを説明する。
②「たくさんのデータを扱うため」が定石だが、ここでは、
「いろいろな⾧さのデータを扱うため」として説明する。
*コンピュータセキュリティでは可変⾧入力の扱いが脆弱性に
つながるため。
2
0x0018fb7F
まずは、プログラムを見て下さい
0x0018fb87
x = 3 (4バイト)
0x0018fb8F
0x0018fb83
1: int x, y, z;
2: int *p;
3:
4: x = 3;
5: y = 4;
6: z = 5;
7:
8: p = &x;
0x0018fb8B
y = 4 (4バイト)
z = 5 (4バイト)
3
0x0018fc00
0x0018fc04
p =
int x,y,zは数字3,4,5を格納するための整数型変数です。
int *pは変数の先頭メモリアドレスを格納するためのポインタ型変数です。
はじめに、どうしてこのような変数p(ポインタ型変数)があるのか
を説明します。
メモリ
“0x0018fb7F” (4バイト)
&はアドレス演算子
と言います。
入力 出力
プログラム
プログラムには入力と出力があります
メモリ
プログラムは、メモリを使って計算します。 4
入力
出力
プログラム
プログラムに、いろいろな⾧さの入力をしたい時があります。
そんな時に、ポインタを使います。
5
Q. どうして、いろいろな⾧さの入力を扱えると便利なのか?
A.例えば、WEBで入力するパスワードを思い出して
ください。パスワードは、人によって⾧さがまちまちです。
WEBのアプリに限らず、世の中のプログラムは、
入力の⾧さが決まっていない(実行前に決められない)
ものがほとんどです。
入力の⾧さの決まっていないプログラムを書くために
必要なポインタ型変数はとても便利な変数です。
6
入力 出力
プログラム
復習:プログラムでは、入力と出力を変数に格納します。
X Y = 3X Y
1 3
X, Y を変数と呼びます。
7
0x0018fb7F
変数とメモリアドレスの関係
0x0018fb80
0x0018fb81
0x0018fb82
0x0018fb83
1: int x;
2: int y;
3:
4: x = 1;
5: y = x * 3;
6:
7: printf(“%d”, y); 0x0018fb8C
0x0018fb8D
0x0018fb8E
0x0018fb8F
0x0018fb8B
1バイト
4バイト
1バイト
4バイト
8
intは4バイトの大きさを持ちます。
int x, int yのような1つの数を
格納する変数をスカラーといいます。
y = 3
入力 出力
プログラム
1つの数字(スカラー)ではなく、
複数の数字の入力ができるプログラムを作りたい時があります
Y = 3
x[i] = {0,1,2}
x[i] Y
複数の数字{0,1,2}を配列と呼びます。
9
0x0018fb7F
配列とメモリアドレスの関係
0x0018fb87
x[0]=0
0x0018fb83
1: int x[4];
2: int y;
3:
4: for ( int = 0; i < 4; i++)
5: x[i] = i;
6:
7:
8: y = 0
9: for ( int i = 0; i < 3; i++)
10: y = y + x[i];
11:
12: printf(“%d”, y); 0x0018fb8F
0x0018fc8B
0x0018fb8B
x[1]=1
x[3]=3
Y
1バイト
4バイト
1バイト
4バイト
10
y = 6
4バイト
4バイト
x[2]=2
4バイト
0x0018fb8F
ここから、本題です。
11
入力 出力
プログラム
いろいろなサイズの配列を入力できるプログラムを作りたい時があります
Y =
6
x[i] ={0,1,2,3}
x[i] = {0,1,2}
x[i] = {0,1}
3
1
x[i] Y
12
配列にはいろいろな⾧さがあることを忘れずに!
ここで、ポインタが登場します。
13
→いろいろなサイズの配列を扱う
0x0018fb7F
ポインタとメモリアドレス(sizeとpに注目)
0x0018fb87
x[0]=0
0x0018fb8F
0x0018fb83
1: int size = 4;
2: int x[size];
3: int *p;
4:
5: p = x;
6:
7: for ( int = 0; i < size; i++)
8: p[i] = i; // <- x[i] = i
9:
10: int y = 0
11: for ( int i = 0; i < size; i++)
12: y = y + p[i];
0x0018fb8F
0x0018fc8B
0x0018fb8B
x[1]=1
x[2]=2
x[3]=3
Y
14
0x0018fc00
0x0018fc04
p:0x0018fb7F
ポインタ
pは、配列の先頭x[0]の
アドレスを指しています。
y = 6: 結果は同じです!
Q. どうして、3行目:int *p なんてものを使うのか?
A.スライド11で、配列には、いろいろな⾧さがある
と言ったことを思い出してください。
→ ポインタを使うと、いろいろな⾧さの配列を扱うこと
ができるようになります。
15
ポインタ
0x0018fb7F
Q. つまり、ポインタpの目的は?
0x0018fb87
x[0]
0x0018fb8F
0x0018fb83
1: int size = N;
2: int x[size];
3: int *p;
4:
5: p = x;
6:
7: for ( int = 0; i < size; i++)
8: p[i] = i;
9:
10: int y = 0
11: for ( int i = 0; i < size; i++)
12: y = y + p[i];
0x0018fb8F
0x0018fc8B
0x0018fb8B
x[1]
x[2]
x[3]
Y
16
0x0018fc00
0x0018fc04
*p 0x0018fb7F
x[N-1]
N
A. ここのメモリ領域
をプログラムに指定し
て、計算させたい!
可変:N
可変:N
0x0018fb7F
Q.もしかして、ポインタpだけでは足りない?
0x0018fb87
X[0] = 0
0x0018fb8F
0x0018fb83
0x0018fb8F
0x0018fc8B
0x0018fb8B
X[1] = 1
X[2] = 2
X[3] = 3
Y
17
0x0018fc00
0x0018fc04
*p 0x0018fb7F
X[N-1] = N-1
size= N
先頭アドレス
0x0018fb7F
5: p = x;
7: for ( int = 0; i < size; i++)
8: p[i] = i;
9:
10: int y = 0
11: for ( int i = 0; i < size; i++)
12: y = y + p[i];
A.そうです。
⾧さの変わる配列を
扱うには、先頭アドレス
とサイズを指定します。
配列
プログラムを書くために、これだけはまず暗記してしまいましょう
ポインタ ポインタを配列にリンクする
int x[3];
??? p[0] = 1;
p = x;
x[0];
x[1];
x[2];
① ②
③
3
この順番が大事です!
int *p;
?
x[0];
x[1];
x[2];

解説#1 C言語ポインタとアドレス