Je dois atsortingbuer de la mémoire à un tableau 3D à l’aide d’un sortingple pointeur.
#include int main() { int m=10,n=20,p=30; char ***z; z = (char***) malloc(sizeof(char**)*m*n*p); return 0; }
Est-ce que c’est correct de faire ça? (Je pense que ce que je fais est incorrect.)
Pour allouer complètement un tableau dynamic 3D, vous devez procéder comme suit:
#include #include 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; }
La libération des données est laissée comme un exercice pour le lecteur.
Il n’est pas nécessaire de convertir la valeur de retour de malloc()
, en C.
Et si vous prévoyez de stocker directement m * n * p
caractères (et de calculer vous-même l’adresse), vous ne devez bien entendu pas redimensionner l’atsortingbution en fonction de la taille d’un caractère char **
.
Vous voulez dire:
int m = 10, n = 20, p = 30; char *z = malloc(m * n * p * sizeof *z);
Cela allouera 10 * 20 * 30 = 6000 octets. Cela peut être vu comme formant un cube de hauteur p
, chaque “tranche” le long de l’axe vertical représentant n * m
octets.
Comme il s’agit d’un adressage manuel, vous ne pouvez pas utiliser, par exemple, z[k][j][i]
pour indexer, mais vous devez utiliser z[k * n * m + j * m + i]
.
Si vous n’avez pas besoin que la mémoire soit allouée dans un seul bloc contigu (l’IME étant le cas habituel), procédez comme suit:
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] } } } } }
Notez que vous devrez libérer cette mémoire dans l'ordre inverse:
for (i = 0; i < m; i++) { for (j = 0; j < n; j++) free(z[i][j]; free(z[i]); } free(z);
Si vous avez vraiment besoin que la mémoire soit allouée dans un bloc contigu, vous avez plusieurs choix. Vous pouvez allouer un seul bloc et calculer vos compensations manuellement:
char *z = malloc(sizeof *z * m * n * p); // note type of z! ... z[i * m + j * n + k] = some_value();
Lorsque vous avez terminé, il vous suffit de faire un seul free
:
free(z);
Si vous avez un compilateur C99 ou un compilateur C11 qui prend en charge les tableaux de longueur variable, vous pouvez procéder de la manière suivante:
int m=..., n=..., p=...; char (*z)[n][p] = malloc(sizeof *z * m);
Cela déclare z
comme un pointeur sur un tableau de caractères n
x p
, et nous allouons m
tels éléments. La mémoire est allouée de manière contiguë et vous pouvez utiliser la syntaxe d'indexation de tableaux à 3 dimensions normale ( z[i][j][k]
). Comme pour la méthode ci-dessus, vous n'avez besoin que d'un seul appel free
:
free(z);
Si vous ne disposez pas d'un compilateur C99 ou d'un compilateur C11 prenant en charge les VLA, vous devez créer des constantes de compilation n
et p
, telles que
#define n 20 #define p 30
sinon cette dernière méthode ne fonctionnera pas.
modifier
m
n'est pas nécessaire que m
soit une constante de compilation dans ce cas, juste n
et p
.
Vous auriez besoin de la boucle nestede suivante –
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); } }
Peut ne pas être synactiquement exact, mais cela devrait être quelque chose dans ce sens.
Vous voulez sizeof(char)
non sizeof(char**)
car ce dernier vous donnera la taille d’un pointeur qui, sur la plupart des systèmes modernes, sera de 4 octets au lieu du 1 attendu.