Присвойте память трехмерному массиву, используя тройной указатель

c pointers memory-management multidimensional-array

10129 просмотра

5 ответа

Я должен назначить память для трехмерного массива, используя тройной указатель.

#include <stdio.h>
int main()
{
    int m=10,n=20,p=30;
    char ***z;
    z = (char***) malloc(sizeof(char**)*m*n*p);
    return 0;
}

Это правильный способ сделать это? (Я думаю, что я делаю неправильно).

Автор: Rog Matthews Источник Размещён: 12.11.2019 09:46

Ответы (5)


6 плюса

Решение

Чтобы полностью выделить трехмерный динамический массив, вам нужно сделать что-то вроде следующего:

#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;
}

Освобождение данных оставлено в качестве упражнения для читателя.

Автор: Paul R Размещён: 28.05.2012 09:03

4 плюса

Нет необходимости приводить возвращаемое значение malloc()в C.

И если вы планируете хранить m * n * pсимволы напрямую (и самостоятельно вычислять адрес), то вам, конечно, не следует масштабировать распределение по размеру a char **.

Ты имеешь в виду:

int m = 10, n = 20, p = 30;
char *z = malloc(m * n * p * sizeof *z);

Это выделит 10 * 20 * 30 = 6000 байтов. Это можно рассматривать как формирование куба высоты p, где каждый «срез» вдоль вертикальной оси является n * mбайтом.

Так как это для ручной адресации, вы не можете использовать, например, z[k][j][i]для индексации, вместо этого вы должны использовать z[k * n * m + j * m + i].

Автор: unwind Размещён: 28.05.2012 09:04

2 плюса

Если вам не нужно выделять память в одном смежном блоке (который обычно используется в 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();

Когда вы закончите, вам просто нужно сделать один free:

free(z);

Если у вас есть компилятор C99 или компилятор C11, который поддерживает массивы переменной длины, вы можете сделать что-то вроде этого:

int m=..., n=..., p=...;
char (*z)[n][p] = malloc(sizeof *z * m);

Это объявляется zкак указатель на массив nx , и мы выделяем такие элементы. Память распределяется непрерывно, и вы можете использовать обычный синтаксис индексации трехмерного массива ( ). Как и в предыдущем методе, вам нужен только один вызов:pcharmz[i][j][k]free

free(z);

Если вы не имеете C99 компилятора или C11 компилятора , который поддерживает Влас, вам нужно будет сделать n, и pвремя компиляции константа, такими как

#define n 20
#define p 30

в противном случае последний метод не сработает.

редактировать

mне нужно быть константой времени компиляции в этом случае, просто nи p.

Автор: John Bode Размещён: 28.05.2012 11:58

0 плюса

Вам понадобится следующий вложенный цикл -

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);
    }
}

Может быть не синактически точным, но это должно быть что-то в этом роде.

Автор: Superman Размещён: 28.05.2012 09:04

0 плюса

Вы sizeof(char)не хотите, так sizeof(char**)как последний даст вам размер указателя, который в большинстве современных систем будет 4 байта вместо ожидаемого 1.

Автор: Jon Cage Размещён: 28.05.2012 09:05
Вопросы из категории :
32x32