PowerPoint プレゼンテーション

CPUとメモリ
メモリ
CPU
32bit
演算部
整数
レジスタ
64bit
小数レジスタ
アドレスバス
データバス
書き込み
読み出し
アドレス
0000
0001
0002
0003
・
・
・
8bit
データの配置
int (32bit = 4byte)
メモリ
8bit
アドレス
・
0120
0121
変数a
0122
・
・
・
変数b
double (64bit = 8byte)
メモリ •メモリは8bit=1byteを
単位に,格納する情報
8bit
アドレス
の大きさに合わせて使
用される
・
0120
•読み書きは,各領域
0121
をひとまとめにして扱う
0122
・ 変数r 左の例:
・
•int a, b; とした場合
・
a は 0120 - 0123
b は 0124 - 0127
•double r; とした場合
r は 0120 - 0127
アドレス
・
0262
0263
0264
・
・
・
8bit
配列型
•配列はメモリ中に順に確保される
左の例:
a[0]
•int a[3]; として配列を定義した場合
確保される領域は全部で 12byte
a[x] は 0262 + (x * 4) から始まる 4byte
a[1]
•double d[10] のようにした場合
確保される領域は全部で 80byte
d[x] は 0262 + (x * 8) から始まる 8byte
a[2]
アドレス
・
0262
0263
0264
0265
0266
・
・
8bit
コンパイラの動作
main() {
int a, b[2];
•「0262」に 10 を入れる
a
a = 10;
コンパイル
b[0] = 20;
b[1] = b[0] + a;
}
b[0]
・メモリを 12byte 確保
(開始位置:0262)
•「0266+0*4」に 20 を入れる
•「0266+0*4」と「0262」の和
を計算し,その結果を
「0266+1*4」に入れる
ここでは,「x」は x から始まる4byteであるとする
b[1]
コンパイラの動作
•変数に必要なメモリの総量を計算する
•各変数名に実際のアドレスを対応づける
•数式を,アドレスを用いた手順に変換する
メモリのアクセス
変数のアクセスに必要な情報
• 読み書きすべき変数は,どのアドレスから始ま
るか
• 変数が格納されている大きさは,いくらか
コンパイラの役目・利点
• アドレスを手計算しなくてよい
• 変数の大きさの代わりに型(int, double など)
を用いるので,間違いにくい.また,大きさの
食い違いをチェックしてくれる
アドレス
・
0262
0263
0264
0265
0266
・
・
8bit
a
ポインタの発想
main() {
int a, b[2];
・・・
}
コンパイラが管理する情報の利用
•変数 a の開始位置(アドレス)を
知りたい
•アドレスを用いてメモリ操作したい
b[0]
b[1]
コンパイラが
管理する情報
•変数 a
開始:0262
大きさ:4
操作単位:4
•変数 b
開始:0266
大きさ:8
操作単位:4
など
開始位置:変数名に対応
大きさ:sizeof(..) で取得可能
操作単位:型に対応
アドレス
・
0262
0263
0264
0265
0266
・
・
8bit
a
b[0]
b[1]
ポインタ
main() {
int a, b[2];
・・・
}
コンパイラが
管理する情報
•変数 a
開始:0262
大きさ:4
操作単位:4
•変数 b
開始:0266
大きさ:8
操作単位:4
& : 変数名からのアドレス取得
&a は 0262 となる
&(b[0]) は 0266 となる
* : アドレスによるメモリアクセス
*(0262) で変数 a へアクセス
できるか?
→操作単位の情報が必要
ポインタ変数とポインタの型
・
0262
0263
0264
0265
0266
・
・
a
b
p
main() {
int a, b, *p;
a = 10;
p = &a;
b = *p;
*p = 20;
}
1.
2.
3.
4.
/*
/*
/*
/*
1
2
3
4
*/
*/
*/
*/
p は int 型の
ポインタ変数
•p には int の変数の
アドレスを代入する
事が出来る
•*p で,p に格納され
ているアドレスから,
int の大きさで
アクセスできる
a に 10 が入る
p に 262 が入る
b に a の値(10)が入る
a に 20 が入る
int a;
int *p;
p = &a;
の解釈
型と文法
p はint変数へのポインタ
a はint変数
int *p;
p = &a;
* はポインタの前に付けると,
そのポインタが指す値を意味
する.つまり,int 型
& は変数の前に付けると,
その型へのポインタを意味する.
つまり,int 型へのポインタ
両辺は「int型」
両辺は「int型へのポインタ」
右辺と左辺の釣り合いが取れていなければならない.
int 型
a
*p
int 型へのポインタ
&a
p
関数とポインタ
a
void change(int *x) {
*x = 100;
}
int main() {
int a = 10;
x
change(&a);
}
•a に格納された値ではなく,変数 a のポインタ(アドレ
ス)を関数 change へ伝える事で,変数 a の内容を書
き換える事が出来る(関数から値を返す事が出来る)
ポインタと配列
int main() {
int a[2] = {10, 20};
int *y = a;
a[0]
*a
a[1]
*(a+1)
y
y[0] = 100;
*(y+1) = 200;
*a = 1000;
*(a+1) = 2000;
y[1]
*(y+1)
y[0] }
*y
•ポインタ変数への加算はアドレスへの
加算ではなく,操作単位(型の大きさ)を
乗じた値の加算となる
•ポインタは配列として,また逆に配列は
ポインタとして使う事が出来る
•a[0] と *a は等価
•a[1] と *(a+1)は等価
ポインタの応用例
int spacecnt(char *p) {
int cnt = 0;
for( ; *p != ‘¥0’; p++)
if(*p == ‘ ‘) {
cnt++;
}
}
return cnt;
}
• 渡された文字列の
スペースの個数を
数えて返す関数
{
• p++ で,文字列の
次の要素へ処理対
象を移動する
Malloc() と free()
int *p;
p = (int *)malloc(100 * sizeof(int));
*p = 100;
p[99] = 200;
free(p);
• 必要なときに必要なだけメモリを確保する
– 大きさの計算に注意(sizeof() を使う事)
– 型の変換(キャスト)をきちんとするのが望ましい
• 使い終わったら解放(free)する
– 解放しなければどんどんメモリが浪費される
構造体
struct foo {
int a;
double d;
};
•x は大きさ 12byte
コンパイル
x.a
struct foo x;
x
•メンバ d は大きさ 8byte で,
開始位置は x の先頭から 4
•x の型は struct foo 型 (foo はタグ名という)
•x.a の型は int
x.d
•メンバ a は大きさ 4byte で,
開始位置は x の先頭から 0
•x.d の型は double
構造体の利点
配列に対する利点
• 様々な型をひとまとめに出来る
• 丸ごとコピーできる
struct hoge a, b;
a = b;
読みやすさ,書きやすさ
• 各要素に意味のある名前を付ける事が出来る
• 構造体の宣言は,タグ名により再利用できる
構造体の作り方・使い方
struct st1 {
int a, b;
}
struct st2 {
struct st1 s;
double c[3];
}
struct st1 x;
struct st2 y;
x.a =10;
y.c[0] = 10.5;
y.s = x;
y.s.b = 20;
作り方(宣言と定義)
• 構造体を入れることが可能
• 配列を入れることも可能
• タグ名を用いていくつでも同じ型
の構造体を作る事が可能
使い方
• メンバへアクセスする演算子.は,
続けて使う事が出来る
構造体へのポインタ
struct st1 {
int a, b;
}
struct st1 x;
struct st1 *y;
y = &x;
(*y).a = 100;
y->b = 200;
構造体を指すポインタが使える
• 演算子*の優先順位は.や[]
より低いことに注意!
• 構造体へのポインタを専門に
扱う演算子->が用意されてい
る
m->n は (*m).n と等価
複雑な変数定義
• int *a[3];
int *(a[3]) と同じ
「a は要素数 3 の配列で,その配
列の各要素はint へのポインタ」
• int (*b)[3];
「b はポインタで,そのポインタが指
す先は要素数 3 の配列.その配列
の各要素は int」
• struct list {
int data;
struct list *p1, *p2;
} x;
「x は int 型の領域 data と,自分
自身と同じ型の構造体を指すポイ
ンタpをメンバに持つ構造体」
a[0]
a[1]
a[2]
int
int
int
int
int
int
b
data
p1
p2
色を塗ってある
部分が実際に確
保されるメモリ
data
p1
p2
data
p1
p2
data
p1
p2
data
p1
p2