リュウグウノツカイのように

深海で悠々と暮らしたい

DXライブラリ/エフェクト描画/配列とアドレスの関係

まえがき

まずはこちらを御覧ください。 youtu.be

この動画では、DXライブラリを用いたアニメーション描画の例を解説しています。 ただ・・・あまりにもプログラムの解説が少ない!もっとちゃんと解説して!という意見がありそうなので、ブログで補足します。

分割のおさらい

 DXライブラリでは、DrawDivGraph関数を使い、1枚の画像を複数の画像に分割し、メモリ内に保存します。メモリ内に保存された画像たちは「ハンドル」という管理番号でプログラム上は扱い、配列でまとめて管理されることで、DrawGraph関数などの描画関連で使用されます。

分割のイメージ

配列を画像に合わせる

 悲しいことに、エフェクト画像は、画像の分割数が違うことがあります。

分割数のちがい

 プログラムで吸収するのも良いですが、下記のようにイチイチ分割数を定めていては大変。

#define DIV_MAX_20 15    //分割数
#define DIV_MAX_20 20    //分割数

int Handle[DIV_MAX_15];  //分割数15用のハンドル
int Handle[DIV_MAX_20];  //分割数20用のハンドル
//キリがない・・・

動的に作成するとは?

 C言語では「メモリを動的に確保する」という技術があります。残念ながら、プログラムが動いている最中に配列が伸び縮みするワケではありません(出来ないことも無さそうですが)。プログラムが実行するとき、状況に合わせて必要なメモリを確保することを、「動的に確保する」と呼んでいます。

配列を静的に作成する

 逆の言葉として「静的に確保する」ということもできます。下記のようなプログラム。静的=定数といったイメージで、プログラムを実行しても、常に素数などサイズは変わらないことを指します。

int Hensu;     //変数の静的確保
int Array[5];  //配列の静的確保  

ポインタはプログラム上の目印

 もう一つ理解しておきたいのは、C言語の鬼門であるポインタ。変数や配列は、パソコンのメモリ空間上に、場所を確保したり破棄されたりするんです。プログラムを実行するときに確保され、プログラムが終了すると破棄。いつも通り静的に変数や配列を作っていたら、大抵は破棄されるのでご安心を。ともかくメモリ上に確保されることがポイント。メモリは空間のそれぞれに、16進数のアドレス(住所)が付けられています。その住所を指し示すのが「ポインタ」なんです。

ポインタのイメージ

ポインタの書き方おさらい

 ポインタはC言語の場合、ポインタ変数という特殊な変数を使います。変数名の前にアスタリスク がついて、「これは普通の変数じゃないですよ~」と、文字通り目印にするんです。ポインタ変数のデータ型は、指し示す部分のデータ型を使います。また、ポインタ変数にはアドレス以外は入れちゃダメです。何が起こるか分かりませんよ~。

int Array[5];  //配列の宣言
int *p;        //ポインタ変数の宣言

配列では先頭アドレスを入れればOK

 配列をポインタで管理したい場合、配列の先頭アドレスを入れて上げればOKです。先頭さえ分かれば、要素数の分だけ順番にアクセスできるからです。配列は連続してデータを確保する構造体の1つ。配列の仕組みを理解すると、ポインタとも仲良くできそうです。

int Array[5];  //配列の宣言
int *p;        //ポインタ変数の宣言
p = &Array[0]; //配列の先頭アドレスをポインタに代入

先頭アドレスは大事!

配列名を指定しない値の入れかた

 ポインタを使用すれば、配列名を指定しなくても、アドレスを間接的に参照して値を入れたり、アクセスしたりできます。そのときに使われるのもアスタリスク今回は「間接参照演算子として再登場です。気をつけるのは括弧の位置。 *p+1 *(p+1) は別モノです。

処理 説 明つまり・・・
*p+1 先頭アドレスへアクセス→間接的に値を取得→その値に+1Array[0]+1と同じ
*(p+1) 先頭アドレスから1つ後(+1)へアクセス→間接的に値を取得Array[0+1]と同じ
int Array[5];  //配列の宣言
int *p;        //ポインタ変数の宣言
p = &Array[0]; //配列の先頭アドレスをポインタに代入
Array[1] = 10; //直接的に、配列の要素に10を代入
*(p+1) = 10;   //間接的に、配列の要素に10を代入

参考)https://www.cc.kyoto-su.ac.jp/~yamada/programming/pointer.html

あとがき

 実際に配列を動的確保する方法は、次回以降で解説予定。今回は配列の先頭アドレスが分かれば、配列がメモリ空間上でどこにあるのか分かるんだ!という部分を理解いただけると良きです。