見出し画像

C言語における多次元配列へのポインタ

C言語における『多次元配列へのポインタ』のサンプルコードと説明です。

1. 配列要素へのポインタ

1.1. 1次元配列とポインタを組み合わせた例

#include <stdio.h>
 
#define NUMBER_OF_COLUMNS   4
 
int main(void)
{
  int linear_array_x[NUMBER_OF_COLUMNS] = {  1,  2,  3,  4};
  int linear_array_y[NUMBER_OF_COLUMNS] = { 11, 12, 13, 14};
 
  int *top_of_columns;
 
  top_of_columns = linear_array_x;
 
  printf("linear_array_x[1] = %d\n", top_of_columns[1]);  /*  2 */
 
  top_of_columns = linear_array_y;
 
  printf("linear_array_y[1] = %d\n", top_of_columns[1]);  /* 12 */
 
  return 0;
}

もっともシンプルな例です。整数型の1次元配列を定義して、配列の先頭要素へのアドレスをポインタ変数 top_of_columns に代入しています。

1.2. 2次元配列とポインタを組み合わせた例

最初の例では『1次元配列の先頭要素(=整数型変数)へのポインタ』であることを強調するために1次元配列を2個用意しました。しかし、よくあるパターンは下記の例のように2次元配列を用意して、2次元配列の一部である『1次元配列の先頭要素のアドレス』をポインタ変数に代入する実装だと思います。

#include <stdio.h>
 
#define NUMBER_OF_ROWS      2
#define NUMBER_OF_COLUMNS   4
 
int main(void)
{
  int square_array[NUMBER_OF_ROWS][NUMBER_OF_COLUMNS]
  = {
      {  1,  2,  3,  4},
      { 11, 12, 13, 14}
    };
 
  int *top_of_columns;
 
  top_of_columns = square_array[0];
 
  printf("square_array[0][1] = %d\n", top_of_columns[1]); /*  2 */
 
  top_of_columns = square_array[1];
 
  printf("square_array[1][1] = %d\n", top_of_columns[1]); /* 12 */
 
  return 0;
}

『整数型の1次元配列』の先頭要素は整数型変数です。だから、その先頭要素へのポインタ変数は int *top_of_columns で辻褄が合っています。そして先頭要素から +1 オフセットした要素を参照するために上記のコードでは top_of_columns[1] という書き方をしています。 *(top_of_columns + 1) という書き方をしても同じ意味になります。

2. 1次元配列へのポインタ

ここからが本題です。C言語で1次元配列へのポインタをどのように記述するかを説明します。

2.1. 1次元配列へのポインタの例

#include <stdio.h>
 
#define NUMBER_OF_ROWS      2
#define NUMBER_OF_COLUMNS   4
 
int main(void)
{
  int square_array_x[NUMBER_OF_ROWS][NUMBER_OF_COLUMNS]
  = {
      {  1,  2,  3,  4},
      { 11, 12, 13, 14}
    };
 
  int square_array_y[NUMBER_OF_ROWS][NUMBER_OF_COLUMNS]
  = {
      { 21, 22, 23, 24},
      { 31, 32, 33, 34}
    };
 
  int (*top_of_rows)[NUMBER_OF_COLUMNS];
  int *top_of_columns;
 
  top_of_rows = square_array_x;
  top_of_columns = top_of_rows[1];
 
  printf("square_array_x[1][1] = %d\n", top_of_columns[1]); /* 12 */
 
  top_of_rows = square_array_y;
  top_of_columns = top_of_rows[1];
 
  printf("square_array_y[1][1] = %d\n", top_of_columns[1]); /* 32 */
 
  return 0;
}

1次元配列へのポインタ変数は int (*top_of_rows)[NUMBER_OF_COLUMNS] というふうに記述します。 ポインタ変数 top_of_rows はただ一つ定義されます。 「NUMBER_OF_COLUMNS個の要素をもつ1次元配列へのポインタ変数」という意味になります。

2.2. ポインタ配列の例

次の例にように変数定義の括弧を省略すると『配列へのポインタ』ではなく『ポインタの配列』の意味になります。

#include <stdio.h>
 
#define NUMBER_OF_ROWS      2
#define NUMBER_OF_COLUMNS   4
 
int main(void)
{
  int square_array[NUMBER_OF_ROWS][NUMBER_OF_COLUMNS]
  = {
      {  1,  2,  3,  4},
      { 11, 12, 13, 14}
    };
 
  int *top_of_columns[NUMBER_OF_ROWS];
 
  top_of_columns[0] = square_array[0];
  top_of_columns[1] = square_array[1];
 
  printf("square_array[0][1] = %d\n", top_of_columns[0][1]); /*  2 */
 
  printf("square_array[1][1] = %d\n", top_of_columns[1][1]); /* 12 */
 
  return 0;
}

int top_of_columns[0] と int top_of_columns[1] の2つのポインタ変数が配列として定義されています。そして上記の例では、2つのポインタ変数にたまたま『異なる2つの変数(配列の先頭要素)のアドレス』を代入しています。複数のポインタ変数が異なる変数を指し示していても、たった一つの変数を指し示していても構いません。上記のサンプルコードはシンプルな内容を持って回った書き方をしているため、ポインタ変数配列を使用する旨味はありませんが、ポインタ変数の使い方次第です。

2.3. 3次元配列とポインタを組み合わせた例

#include <stdio.h>
 
#define NUMBER_OF_PAGES     2
#define NUMBER_OF_ROWS      3
#define NUMBER_OF_COLUMNS   4
 
int main(void)
{
  int cubic_array[NUMBER_OF_PAGES][NUMBER_OF_ROWS][NUMBER_OF_COLUMNS]
  = {
      {
        {  1,  2,  3,  4},
        { 11, 12, 13, 14},
        { 21, 22, 23, 24},
      },
      {
        {101,102,103,104},
        {111,112,113,114},
        {121,122,123,124},
      },
    };
 
 
  int (*top_of_rows)[NUMBER_OF_COLUMNS];
  int *top_of_columns;
 
  top_of_rows = cubic_array[0];
  top_of_columns = top_of_rows[1];
 
  printf("square_array[0][1][1] = %d\n", top_of_columns[1]); /* 12 */
 
  top_of_rows = cubic_array[1];
  top_of_columns = top_of_rows[1];
 
  printf("square_array[1][1][1] = %d\n", top_of_columns[1]); /*112 */
 
  return 0;
}

ここまで複雑になると何がなんやらですが、上記の例では3次元配列を使い2次元配列を2個定義しています。そして2次元配列の先頭要素(=1次元配列へのポインタ)を top_of_rows に代入しています。 top_of_rows も top_of_columns も1個しかため異なる配列要素を参照するために値の上書きをおこなっています。

3. 2次元配列へのポインタ

下記が3次元配列を2個定義して、2次元配列へのポインタに代入する例です。

#include <stdio.h>
 
#define NUMBER_OF_PAGES     2
#define NUMBER_OF_ROWS      3
#define NUMBER_OF_COLUMNS   4
 
int main(void)
{
  int cubic_array_x[NUMBER_OF_PAGES][NUMBER_OF_ROWS][NUMBER_OF_COLUMNS]
  = {
      {
        {  1,  2,  3,  4},
        {  5,  6,  7,  8},
        {  9, 10, 11, 12},
      },
      {
        { 13, 14, 15, 16},
        { 17, 18, 19, 20},
        { 21, 22, 23, 24},
      }
    };
 
  int cubic_array_y[NUMBER_OF_PAGES][NUMBER_OF_ROWS][NUMBER_OF_COLUMNS]
  = {
      {
        {101,102,103,104},
        {105,106,107,108},
        {109,110,111,112},
      },
      {
        {113,114,115,116},
        {117,118,119,120},
        {121,122,123,124},
      }
    };
 
  int ((*top_of_array)[NUMBER_OF_ROWS])[NUMBER_OF_COLUMNS];
  int (*top_of_page)[NUMBER_OF_COLUMNS];
  int *top_of_row;
 
  top_of_array = cubic_array_x;
  top_of_page  = top_of_array[1];
  top_of_row   = top_of_page[1];
 
  printf("array_x[1][1][1] = %d\n", top_of_row[1]);
 
  top_of_array = cubic_array_y;
 
  printf("array_y[1][1][1] = %d\n", top_of_array[1][1][1]);
 
  return 0;
}

int ((*top_of_array)[NUMBER_OF_ROWS])[NUMBER_OF_COLUMNS] と記述することで2次元配列へのポインタを定義することができます。括弧の位置が重要です。括弧を省略してしまうと『配列へのポインタ』ではなく『ポインタの配列』になります。4次元配列を定義して2次元配列へのポインタに代入することもできますが、配列定義が煩雑になるためサンプルコードは省きます。

以上、『配列へのポインタ』の説明でした。

この記事が気に入ったらサポートをしてみませんか?