トリプル ポインターを使用してメモリを 3D 配列に割り当てる必要があります。
#include <stdio.h>
int main()
{
int m=10,n=20,p=30;
char ***z;
z = (char***) malloc(sizeof(char**)*m*n*p);
return 0;
}
これは正しい方法ですか?(私がしていることは間違っていると思います。)
トリプル ポインターを使用してメモリを 3D 配列に割り当てる必要があります。
#include <stdio.h>
int main()
{
int m=10,n=20,p=30;
char ***z;
z = (char***) malloc(sizeof(char**)*m*n*p);
return 0;
}
これは正しい方法ですか?(私がしていることは間違っていると思います。)
3D 動的配列を完全に割り当てるには、次のようにする必要があります。
#include <stdio.h>
#include <stdlib.h>
int main()
{
int m=10,n=20,p=30;
char ***z;
z = malloc(m * sizeof(char **));
assert(z != NULL);
for (i = 0; i < m; ++i)
{
z[i] = malloc(n * sizeof(char *));
assert(z[i] != NULL);
for (j = 0; j < n; ++j)
{
z[i][j] = malloc(p);
assert(z[i][j] != NULL);
}
}
return 0;
}
データの解放は、読者の課題として残されています。
malloc()
C では ,の戻り値をキャストする必要はありません。
また、文字を直接格納する (そしてアドレスを自分で計算する) ことを期待しているm * n * p
場合は、もちろん、 のサイズで割り当てをスケーリングしないでください char **
。
もしかして:
int m = 10, n = 20, p = 30;
char *z = malloc(m * n * p * sizeof *z);
これにより、10 * 20 * 30 = 6000 バイトが割り当てられます。p
これは、縦軸に沿った各「スライス」がn * m
バイトである、高さの立方体を形成していると見なすことができます。
これは手動のアドレス指定用であるため、 egz[k][j][i]
を使用してインデックスを作成することはできません。代わりに を使用する必要がありますz[k * n * m + j * m + i]
。
単一の連続したチャンク (IME が通常のケース) にメモリを割り当てる必要がない場合は、次のようにします。
char ***z;
z = malloc(sizeof *z * m); // allocate m elements of char **
if (z)
{
int i;
for (i = 0; i < m; i++)
{
z[i] = malloc(sizeof *z[i] * n); // for each z[i],
if (z[i]) // allocate n elements char *
{
int j;
for (j = 0; j < n;j++)
{
z[i][j] = malloc(sizeof *z[i][j] * p); // for each z[i][j],
if (z[i][j]) // allocate p elements of char
{
// initialize each of z[i][j][k]
}
}
}
}
}
このメモリを逆の順序で解放する必要があることに注意してください。
for (i = 0; i < m; i++)
{
for (j = 0; j < n; j++)
free(z[i][j];
free(z[i]);
}
free(z);
メモリを連続したチャンクに割り当てる必要がある場合は、いくつかの選択肢があります。単一のブロックを割り当てて、オフセットを手動で計算できます。
char *z = malloc(sizeof *z * m * n * p); // note type of z!
...
z[i * m + j * n + k] = some_value();
完了したら、次の 1 つの操作を行うだけですfree
。
free(z);
可変長配列をサポートする C99 コンパイラまたは C11 コンパイラがある場合は、次のようにすることができます。
int m=..., n=..., p=...;
char (*z)[n][p] = malloc(sizeof *z * m);
これは のx配列z
へのポインタとして宣言し、そのような要素を割り当てます。メモリは連続して割り当てられ、通常の 3 次元配列インデックス構文 ( ) を使用できます。上記のメソッドと同様に、1 回の呼び出しのみが必要です。n
p
char
m
z[i][j][k]
free
free(z);
VLA をサポートする C99 コンパイラまたは C11 コンパイラがない場合は、次のようなコンパイル時定数n
を作成する必要があります。p
#define n 20
#define p 30
そうしないと、最後の方法は機能しません。
編集
m
この場合、コンパイル時の定数である必要はありませn
んp
。
次のネストされたループが必要です-
z = (char**)malloc(sizeof(char*) * m);
for (int i = 0; i < m; ++i)
{
*(z + i) = (char*)malloc(sizeof(char*) * n);
for (int j = 0; j < n; ++j)
{
*(*(z + i)) = (char)malloc(p);
}
}
構文的に正確ではないかもしれませんが、これらの線に沿ったものでなければなりません。
後者は、ほとんどの最新のシステムでは、期待する 1 ではなく 4 バイトになるポインターのサイズを提供するため、望ましくsizeof(char)
ありません。sizeof(char**)