「組み込み」ならではの基礎知識 ――スタートアップ・ルーチンからハードウェアまで

セサミアン3人組

tag: 組み込み

技術解説 2003年5月14日

3 array[-1]はなぜ動くのか(配列の実体)

 プログラムを作るとき,配列ほど使いやすいものはありません.そのため,いつのまにか「配列」という抽象的な概念が頭の中にでき上がって,何か特別なもののように思っていませんか? ここでは,C言語における配列の実体に迫ります.

●メモリ空間のイメージを思い浮かべよう

 配列を使うときに注意するべきことは,例えば,

  int array[10];

と宣言した場合,array[0],array[1],...,array[9]というように「インデックスは0から9を使うこと」です.インデックスをこの範囲で使うというのが,礼儀正しいプログラムの作りかたです.しかし,範囲を超えたインデックスを使ってもプログラムは動作します(動作として正しいかどうかは別として).極端な話,array[-1]でも動きます.なぜなのか説明できますか?配列という概念だけでこれを説明することはできません.配列の実体を考えます.

 まず,メモリ空間のイメージを頭に思い浮かべましょう.メモリ空間とは,プログラムのコードやデータを配置するための(論理的な)場所で,実際にはマイコンの内蔵メモリやマイコン外部にあるRAMやROMに存在します注3-1.MMU(memory management unit)を搭載するマイコンもありますが,ここでは説明を簡単にするためにMMUはないものとします.メモリ空間にはアドレスが割り振られ,それによってユニーク(一意)にどこのメモリかを指定できます.メモリ空間のアドレスは,例えば32ビットを使って表現すれば,0x00000000番地から0xffffffff番地まで割り振ることができますが,実際に使用する際にはこれらのすべてのアドレスが使えるわけではありません.アドレスに対応するメモリが実装されている部分のみ使えることになります.例えば図3-1では,0x00000000番地から0x0000ffff番地までと0xffff0000番地から0xffffffff番地までが使用できることを示しています.

 さて,配列arrayはこのメモリ空間の中でどのように存在しているのでしょうか?図3-1では,配列arrayは0x1020番地から0x1047番地までに配置されています.これによりarray[0]は0x1020番地,array[1]は0x1024番地,array[2]は0x1028番地,...となります.これらのアドレスは,配列の各要素のそれぞれに対して何番地と割り振るわけではなく,配列の先頭アドレスとオフセットから計算されます.つまり,array[5]の場合,

 array[5]のアドレス = 配列arrayの先頭アドレス + 5番目の要素のオフセット
           = 0x1020 + 5 × sizeof(int)
           = 0x1020 + 0x14 = 0x1034 (3-1)

となります.つまり,配列の先頭アドレスさえ決まれば,インデックスと配列の型からわかるデータ長(この例ではsizeof(int))から配列の各要素のアドレスがわかることになります.つまり,配列を利用するにはメモリ空間上の連続した場所があればよいわけです.

 注3-1;メモリ空間については,「8.メモリとポート」も参照していただきたい.


f03_01.gif
〔図3-1〕配列はメモリ空間上にどのように存在するか
ここに図示したメモリ空間のうちグレーの部分は,実際にメモリが実装されているアドレス(実際に使えるメモリ部分)を示している.配列の実体は,メモリ空間上に張り付いた,ある領域にすぎない.

組み込みキャッチアップ

お知らせ 一覧を見る

電子書籍の最新刊! FPGAマガジン No.12『ARMコアFPGA×Linux初体験』好評発売中

FPGAマガジン No.11『性能UP! アルゴリズム×手仕上げHDL』好評発売中! PDF版もあります

PICK UP用語

EV(電気自動車)

関連記事

EnOcean

関連記事

Android

関連記事

ニュース 一覧を見る
Tech Villageブログ

渡辺のぼるのロボコン・プロモータ日記

2年ぶりのブログ更新w

2016年10月 9日

Hamana Project

Hamana-8最終打ち上げ報告(その2)

2012年6月26日