第61章 多次元配列

 例えば九九表を作るとします。この情報を nKuKu[9 * 9] という配列変数に入れるのも不格好です。今回はこういうときのための方法について話します。


 では、今回の要点です。


 では、いってみましょう。


 先ず、始めに言った通り九九表を作って、それを一旦変数に入れてみようと思います。さて、多くの連続したデータを1つの変数で扱うということから、配列変数を使うことになるのはすぐ分かることと思います。

 さて、今まで話したことだけでは、

const int KUKU_LIMIT = 9;
int       nKuKu[KUKU_LIMIT * KUKU_LIMIT];
int       i, j;

for(i = 1; i <= KUKU_LIMIT; i++)
    for(j = 1; j <= KUKU_LIMIT; j++)
        nKuKu[(i - 1) * KUKU_LIMIT + (j - 1)] = i * j;

ということになるでしょう。九九表の対称性を利用して、処理を軽減することもできますね(これについては、自分で考えてみて下さい)。

 で、i * j の値を取り出すときは nKuKu[(i - 1) * KUKU_LIMIT + (j - 1)] です(i * j とすればいいというミもフタもないことは言いっこなしです(^ ^;)。

 これらは非常に分かりにくいですね。このようなときのために、番号をいくつもとれるような配列を作ることができます。それが多次元配列です。

 では、次のプログラムを見て下さい。

プログラム実行結果
// Array2.cpp
#include <stdio.h>

int main()
{
    const int KUKU_LIMIT = 9;
    int       nKuKu[KUKU_LIMIT][KUKU_LIMIT];
    int       i, j;

    for(i = 1; i <= KUKU_LIMIT; i++)
        for(j = 1; j <= KUKU_LIMIT; j++)
            nKuKu[i - 1][j - 1] = i * j;

    printf("    1  2  3  4  5  6  7  8  9\n");
    for(i = 1; i <= KUKU_LIMIT; i++)
    {
        printf(" %d ", i);
        for(j = 1; j <= KUKU_LIMIT; j++)
            printf("%2d ", nKuKu[i - 1][j - 1]);
        putchar('\n');
    }

    return 0;
}
    1  2  3  4  5  6  7  8  9
 1  1  2  3  4  5  6  7  8  9
 2  2  4  6  8 10 12 14 16 18
 3  3  6  9 12 15 18 21 24 27
 4  4  8 12 16 20 24 28 32 36
 5  5 10 15 20 25 30 35 40 45
 6  6 12 18 24 30 36 42 48 54
 7  7 14 21 28 35 42 49 56 63
 8  8 16 24 32 40 48 56 64 72
 9  9 18 27 36 45 54 63 72 81

 この nKuKu[KUKU_LIMIT][KUKU_LIMIT] というのが多次元配列です。こうすると、番号を2つ取ることのできる配列になります。取る番号の数が2つなので、2次元配列とも言います。

 番号によって、それぞれが違う変数を示すことになります。片方が同じ番号でも、もう片方の番号が違えば別の変数になります。

 この配列の要素にアクセスするためには、それぞれの [ ] に番号を入れるだけです。たとえば、4×6は nKuKu[3][5] に入れればいいですし、7×1は nKuKu[6][0] に入れればいいのです(もちろん、nKuKu[5][3], nKuKu[0][6] に入れたのでも別に構いませんが)。


 今回の例は2次元配列でしたが、もちろん、3次元、4次元、5次元配列なども作れます。それらも、[ ] の数を増やすだけで簡単に作ることができます。

 では、と、調子に乗って次のような配列変数を作ってしまうと、ちょっと厄介です。

int array[256][256][256];

 一見何の変哲もないようですが、この変数のサイズは一体いくらになるでしょうか? 256×256×256×4=67108864バイト、すなわち64メガバイトになります。

 第3部で話す予定ですが、メモリの総量とは別に、内部変数のサイズの総量にはある限りがあります。この総量は普通1メガバイト程度であり(2000年7月25日現在)、64メガバイトというのはこの総量を越えてしまいます(このことをスタックオーバーフローといいます)。このサイズは変更できますが、それでも64メガバイトは大きいでしょう。

 では、グローバル変数ではどうなのかといえば、それならとりあえず動くでしょう。ですが、64メガバイトはちょっと大きすぎて、メモリが足りないと起動できなくなるでしょう。

 int array[16777256]; としていればその無茶さはわかりますが、3次元配列にすると各番号が小さくなり、パッと見無茶な大きさかどうかが分かりにくくなります。多次元配列を作る際は、きちんとサイズを確認しましょう。

 もちろん、1次元配列でも、無茶なサイズの配列変数は作らないようにしましょう。

補足:このような大きな配列を作るとき、普通は、後に話す「メモリの動的確保」というものを使います。ですが、16メガバイトとなると、スペックの低い環境ではそれでもメモリが足りないこともあるでしょう。そういうメモリを確保する方法もありますが、方法はOSに依存することになります。ファイルを利用して一度にメモリ上に置くデータを減らすという手、使わないデータを圧縮しておくという手など、メモリにのらないほどの巨大配列を扱うにはいろいろ工夫が必要でしょう。


 では、最後に今回の要点です。


 次回は、多次元配列の初期化とメモリ上でのデータの並び方について話します。では。


第60章 構造体3 | 第62章 多次元配列2

Last update was done on 2009.9.13

この講座の著作権はロベールが保有しています