二次元配列で位置を指定する方法を教えてください。添字付けによって値を取得するという意味ではありませんが、1D 配列に似た方法で、ポインターを指定すると、+
演算子を使用してその位置に移動できます。
たとえばA
、サイズ 4 の配列がある場合、 で 3 番目の要素に移動できますA + 2
。
2D 配列がある場合、これを行うにはどうすればよいですか?
質問は不明確ですが、ここにいくつかの考えがあります。
この言語には多次元配列はありません。1 次元配列のみがサポートされており、追加の保証がいくつかあります。一般に 2D 配列と呼ばれるものは、特定の型の配列型のオブジェクトの 1D 配列です。追加の保証は、連続性と整列の保証です。配列内の各要素は、配列内の次の要素と連続しており、配列と最初の要素は整列されています。
配列は最初の要素へのポインターに減衰する傾向があり、ポインター演算を使用して配列内の次の要素に移動できます。これにより、構文のA + 2
意味が可能になります&A[0] + 2
。配列の最初 (0 番目) の要素。ただし、減衰は最上位の配列のみです。
前に説明した保証は、最初の要素へのポインターであるかのように配列を使用できること、およびその要素が配列自体とまったく同じ場所にあることを意味します。これをネストされた配列に再帰的に適用すると、次のようになります。
int array[10][10];
// array is an array of 10 arrays of 10 int
// array[0] is an array of 10 int, the first subarray
// array[0][0] is an int, the first element of the subarray
int *p = &array[0][0];
int *q = p + 10; // One beyond the first subarray: pointer to the first
// element of the second subarray.
int *r = p + 10*row + col; // pointer to the col-th element inside the row-th subarray
// equivalent to &array[row][col]
ポインター演算に基づく他の回答は技術的には正しいですが、配列が A[rows][cols] のように割り当てられていることが確実な場合に限ります。多くの場合、これは当てはまりません。配列をそのように実装したとしても、別の開発者がそれをリファクタリングしないとは確信できません。他の開発者がタイプ A[rows][cols] を vector< vector< type > > A に変更した瞬間、あなたのコードは壊れてしまいます。
したがって、行間でポインター演算を使用しないことをお勧めします。パフォーマンスが心配な場合は、心配しないでください。コンパイラは、必要に応じてポインター演算を使用して配列要素にアクセスします。さらに重要なことに、コンパイラは、該当しない場合はポインター演算を使用しません。
一度に 1 つのレベルを逆参照します。2D 配列と 3D 配列の場合:
#include <cstdio>
int A[2][2];
int B[2][2][2];
int main() {
// Set A[1][1] to 2
*(*(A+1) + 1) = 2;
printf("%d\n", A[1][1]);
// Set B[1][1][1] to 3
*(*(*(B+1) + 1) + 1) = 3;
printf("%d", B[1][1][1]);
}
一般*(...*(*(array_of_N_dimensions + D1) + D2) ... + DN)
に、 へのアクセスが提供されますarray_of_N_dimensions[D1][D2]...[DN]
。
ここにあなたのための自己教育テストコードがあります。それが役立つことを願っています。
#include < iostream >
int main()
{
int a[2][2];
a[0][0] = 1;
a[0][1] = 2;
a[1][0] = 3;
a[1][1] = 4;
for (int i=0; i < 4; ++i)
{
std::cout << *(*a+i) << std::endl;
}
return 0;
}
2 次元配列は行ごとにメモリに格納されるため、N が行の長さであるインデックスA[i][j]
を使用してアクセスできます。 A+i*N+j