Document

2005年度
データ構造とアルゴリズム
第2回
「C言語の復習:配列」
西尾 信彦 [email protected]
立命館大学情報理工学部
情報システム学科
配列
• 配列とは?
– 同一型の変数が(メモリ上に隣接して)並んだもの
• 宣言の仕方
– 配列のデータ型 配列名[配列の大きさ];
– 例:
• int sample[4]; ⇒int型のデータの入る変数4個分を宣言
• char name[32]; ⇒char型のデータの入る変数32個分を宣言
• []の中は0から始まる
– “[]”は添字演算子とも呼ばれる
• int sample[4]; と宣言すれば
• sample[0], sample[1], sample[2] ,sample[3]
のint型のデータが格納できる4つの変数
を宣言したことになる。
配列の例:
#include <stdio.h>
int main(){
int sample[4];
int i;
for(i = 0; i < 4; i++){
sample[i] = i + 1;
printf("sample[%d] = %d\n", i, sample[i]);
}
}
実行結
果:
sample[0] = 1
sample[1] = 2
sample[2] = 3
sample[3] = 4
変数のチェック
~正しいプログラムを書くために~
• コンパイラにできること
– コンパイラには配列は判断できない?
– だから気をつけないと
• 動かしてみないとわからないこと
– C言語はやってくれない
– だから気をつけないと!
ポインタ(というデータ)とは?
• 変数のメモリ上での位置を表わすデータ
• ポインタというデータの正体:
– それが 指す変数が格納された
メモリ上の先頭アドレスと
– 指す変数に格納されるデータのサイズによって
表わす
• ポインタデータの作り方
– そのポインタが指したい変数の頭に&をつける
– &は実は演算子(アドレス演算子)
しかし,このデータをどう使う?
• そのままでは代入くらいにしか使えない
– 代入式の右辺と左辺
– 右はデータ,左は変数って気づいてた?
• ポインタ変数の宣言の仕方(作り方)
– データ型 *変数名;
– 例: int *value;
• ポインタ演算
– ポインタの足し算,引き算
ポインタの例:
#include <stdio.h>
int main(void){
int data = 33;
int *data_pointer;
data_pointer = &data; /* dataのアドレスをdata_pointerに代入*/
printf("data = %d\n", data);
printf("&data = %d (%x)\n", &data, &data); /* dataのアドレスを参照 */
printf("*data_pointer = %d\n", *data_pointer); /* アドレス先の値を参照 */
printf("data_pointer = %d (%x)\n", data_pointer, data_pointer);
}
実行結果:
data = 33
&data = 1245064 (12ff88)
*data_pointer = 33
data_pointer = 1245064 (12ff88)
演算子と式
• 演算子は計算するためのもの
–
–
–
–
–
例 四則演算(+-*/)は知ってますよね?
[数字] [演算子] [数字] と並べるけど
[演算子] [数字] なんてのもある
さらに数字は式でもいい
演算子には優先度があるので()が必要
• 計算したら結果(答)が出る
–
–
–
–
–
–
式を計算したら答が出る
C言語では、「式を評価すると値が出る」という
&も*も演算子
--も++も演算子
[]も実は演算子
さらに””も=も演算子
• *は中置演算子の場合は乗算
– A * (B + C)
• *は前置演算子の場合はポインタの指す先
– *A = *B * 2
• ++と—は前置と後置ができる
– 評価した値が違うだけ
– 1加減した後の値と1加減する前の値
• &は変数を評価してその変数へのポインタを値とする
*はその逆
– & [変数]  ポインタ
– * [ポインタ]  変数
配列とポインタの関係
• 配列名はその配列の第0要素へのポインタ
– int array[100];
– arrayは&(array[0])と同じ
• しかし,
– 配列名は変数ではないので代入できないことに
注意
– 配列は各要素が隣接しているのを利用できるの
で便利
配列とポインタの例:
#include <stdio.h>
#define ARRAY_LENGTH 3
int main( ){
int intMemory[ARRAY_LENGTH];
int *pointer;
int i;
pointer = &intMemory[0]; // ポインタの初期値を配列の先頭アドレスに設定
for(i = 0; i < ARRAY_LENGTH; i++){
scanf("%d", pointer);
// 整数の入力.
pointer++; // ポインタを1 つずらす
}
printf("値: アドレス\n");
pointer = intMemory;
// ポインタの初期値を配列の先頭アドレスに設定
for(i = 0; i < ARRAY_LENGTH; i++){
printf("%d: %x\n", *pointer, pointer);
pointer++;// ポインタを1 つずらす
}
}
実行結果:
32
56
78
値: アドレス
32: 12ff80
56: 12ff84
78: 12ff88
ところで...
• 変数はいつできて,いつなくなるのか?
• どこから参照できるのかも重要
• ものによって違う
– 静的変数
• ローカル変数
• グローバル変数
– 動的変数 (未出,来週やります)