プログラム再構成に関する 特許申請について

オブジェクト指向言語論
第六回
知能情報学部
新田直也
配列の宣言

配列:任意にアクセスできる変数の列.
a[0]

a[1]
a[2]
a[3]
a[4]
…
配列名と添字
a[3]
配列名 添字 (C, C++, Javaの場合,先頭は0番)

配列宣言
int a[1000];
使用する要素数
配列宣言(Java, VB)

Javaの配列宣言
int[] a = new int[1000];

VBの配列宣言
Dim a(1000) as Integer
多次元配列


たとえば表のデータを扱う場合(2次元配列).
a[0][0]
a[0][1]
a[0][2]
a[0][3]
a[1][0]
a[1][1]
a[1][2]
a[1][3]
a[2][0]
a[2][1]
a[2][2]
a[2][3]
多次元配列の宣言
int a[3][4];
12個のint型の要素が用意される.
配列とメモリ

配列の要素はメモリ上に連続して配置される.
:
0xffff番地
a[3]
b[1][0]
a[2]
b[0][2]
a[1]
a
a[0]
0xffff番地
b[1]
b[0][1]
b, b[0]
b[0][0]
0x0000番地

:
0x0000番地
配列名で先頭アドレスを参照することもできる
(参照のみで代入はできない).
スタック領域の詳細

関数呼出しに応じて
スタック領域が確保される.
main () {
int x = 1;
x = input(x);
}
int input(int y) {
char s[10];
scanf(“%s”, s);
printf("%s\n", s);
return y + 1;
}
0xffff番地
main用
x
:
y
戻り番地
:
s[1]
s[0]
引数用
20バイト
input用
自動変数用
28バイト
0x0000番地
バッファオーバーフロー攻撃

scanfなどで戻り番地を上書きする.

戻り番地は29~32文字目
main () {
int x = 1;
x = input(x);
}
int input(int y) {
char s[10];
scanf(“%s”, s);
printf("%s\n", s);
return y + 1;
}
0xffff番地
main用
x
:
y
戻り番地
:
不正な
s[1]
コード
s[0]
引数用
20バイト
input用
自動変数用
28バイト
0x0000番地
1次元配列の引数渡し

配列名は配列の先頭アドレス.
main() {
int a[100];
:
func(a);
:
}
void func(int x[]) {
受け側は要素数を指定しない.
int *x で受けても良い.
いずれにせよサイズがわからな
いので注意.
2次元配列の引数渡し

配列名は配列の先頭アドレス.
main() {
int a[100][10];
:
func(a);
:
}
:
0xffff番地
a[1][0]
a[0][9]
:
a[0][1]
int が 10 個分
a[0][0]
0x0000番地
void func(int x[][10]) {
受け側は最高次元の要素数を
指定しない.
ポインタ

ポインタをURL,ポインタが指す先をWebページと
考えてみる.
アドレスが指す先の内容
int *p;
アドレス
p は指す先が int 型であるポインタ
*p
p
http://www.hogehoge.com
<html>
<body>
<H1>5</H1>
</body>
</html>
ポインタの更新と参照先の更新

p の値の変更と *p の値の変更の違い.
*p = 7; → Webページの更新
*p
p
http://www.hogehoge.com
http://www.hogehoge2.com
*p
p = q;
→ リンク先の変更
7
7
<html>
<body>
<H1>5</H1>
7
</body>
</html>
アドレスの取得

配列の先頭アドレス:
int a[1000];
と宣言したときの a (配列名)

変数のアドレス:
int x;
アドレス
内容
と宣言したときの &x
ポインタを用いた値の共有

以下のプログラムを実行してみる.
内容
int x;
int *p;
アドレス
p = &x;
このとき x の値も同時に 3 になる
*p = 3;
値呼出しと参照呼出し

値呼出し:
関数に実引数の値を渡すが,呼出しによって実引数の値が
変更されることはない.
12
:
12 12
x
func(a);
a
:
void func(int x) {

参照呼出し:
:
関数に実引数の参照(ポインタ)を渡す.関数内部で実引数
の値が変更することが可能である.
:
12
func(&a);
a
:
void func(int *x) {
参照渡し(2)

厳密には参照渡しも値渡しの一種である.
14
12
a
1536
1536
:
func(&a); &a = 1536
:
x
void func(int *x) {
:
*x = 14;