したがって、私の理解が正しければ、必要なのは 3 つのrxr配列 ( a、b、およびc) ですが、3 つすべてを連続して格納する必要があります。基本的に、バッキング ストアは単一の 3 x rxr配列になります。
rコンパイル時にサイズがわからず、可変長配列をサポートする C99 または C11 実装で作業している場合は、次のようにすることができます。
size_t r = ...;
double (*a)[r] = NULL;
double (*b)[r] = NULL;
double (*c)[r] = NULL;
double (*backing_store)[r][r] = malloc(3 * sizeof *backing_store);
if (!backing_store)
{
// panic and exit
}
a = backing_store[0];
b = backing_store[1];
c = backing_store[2];
次にa、 、b、およびcを通常の のrxr配列であるかのように使用できdoubleます。
a[i][j] = ...;
printf("%f\n", b[x][y]);
等
完了したら、次のように解放するだけですbacking_store。
free(backing_store);
なぜこれが機能するのですか?
式のbacking_store型は "の -要素配列 の -r要素配列へのポインターrですdouble。式backing_store[i]は と同等であるため*(backing_store + i)、添字演算子は暗黙的にポインターを逆参照します。そのため、式の型は " r-要素配列 のr-要素配列double" になります。それぞれ、backing_store[0]、backing_store[1]およびbacking_store[2]のrxr配列ですdouble。
ほとんどのコンテキストでは、型 " N-element array of T" の式は、型 "pointer to T" の式に暗黙的に変換 ("減衰") され、その値は配列内の最初の要素のアドレスになることに注意してください。
したがって、式backing_store[0]は型 " r-element array of r-element array of double" から "pointer to r-element array of double" に変換され、これはたまたま の型でaあり、値は最初のサブ配列のアドレスです (これが発生します)。と同じになるbacking_store)。ここでも、添字演算子を適用すると暗黙的にポインターが逆参照されるため、の後に th 配列の th 要素がa[i][j]与えられます。 jia
r がコンパイル時にわかっている場合(つまり、定数式である場合)、手順は同じです。変数を宣言する必要はありませんr。
#define R ...
double (*a)[R] = NULL;
double (*b)[R] = NULL;
double (*c)[R] = NULL;
double (*backing_store)[R][R] = malloc(3 * sizeof *backing_store);
if (!backing_store)
{
// panic and exit
}
a = backing_store[0];
b = backing_store[1];
c = backing_store[2];
rがコンパイル時に不明で、(VLA をサポートしない C89 または C11 コンパイラを使用して) 可変長配列を使用できない場合は、少し複雑になる可能性があります。ここでは、 を 1 次元配列として扱い、1次元添字を各部分配列に計算します。backing_storedouble
double *a = NULL;
double *b = NULL;
double *c = NULL;
double *backing_store = malloc(3 * r * r * sizeof *backing_store);
if (!backing_store)
{
// panic
}
a = backing_store;
b = backing_store + r * r;
c = backing_store + 2 * r * r;
a[i*r+j] = ...;
printf("%f\n", b[x*r+y]);
繰り返しますが、backing_store完了したら解放する必要があります。
free(backing_store);
2 次元添字を使用するほどきれいではありませんが、動作するはずです。