Выделите многомерный массив негарантированного размера в куче, сохраняя синтаксис индексации массива - PullRequest
0 голосов
/ 04 февраля 2020

Я пишу небольшую вещь с участием вокселей, поэтому у меня есть 3D-массив, заполненный данными, например,

typedef struct data{float m,vx,vy,vz;} data;
data pool[2][x][y][z];
data voronoi[26];

, где x, y и z равны uint64_t. Но их фактическое значение зависит от пользовательского ввода во время выполнения. Теперь получается, что я получаю ошибку сегментации, когда массив становится слишком большим (даже не могу сделать 128x128x128), даже если у меня более чем достаточно оперативной памяти. Поэтому мне нужно выделить его в кучу. Как мне это сделать, хотя также не нужно преобразовывать код следующим образом:

uint64_t h,b,d,p;
p = 0;
for(h=1;h<y-1;++h){
for(b=1;b<x-1;++b){
for(d=1;d<z-1;++d){
voronoi[ 0] = pool[p][h-1][b-1][d-1];
voronoi[ 1] = pool[p][h  ][b-1][d-1];
voronoi[ 2] = pool[p][h+1][b-1][d-1];
voronoi[ 3] = pool[p][h-1][b  ][d-1];
voronoi[ 4] = pool[p][h  ][b  ][d-1];
voronoi[ 5] = pool[p][h+1][b  ][d-1];
voronoi[ 6] = pool[p][h-1][b+1][d-1];
voronoi[ 7] = pool[p][h  ][b+1][d-1];
voronoi[ 8] = pool[p][h+1][b+1][d-1];
    //etc until 26

}}}
p = 1;
// repeat cycle, then p=0 again, etc

Просто malloc пул, например, так:

data* pool=(2*x*y*z*sizeof(data));

не дубликат, потому что mallo c массив 1d и добавление пользовательской индексации (ответ goto) делает недействительным синтаксис индексации многомерных квадратных скобок.

1 Ответ

2 голосов
/ 04 февраля 2020

Simple. Используйте указатель на многомерный массив:

data (*pool)[x][y][z] = malloc(2*sizeof(*pool));
...
for(h=1;h<y-1;++h){
    for(b=1;b<x-1;++b){
        for(d=1;d<z-1;++d){
            voronoi[ 0] = pool[p][h-1][b-1][d-1];
            ...
}
...
free(pool);

Обратите внимание, что самое внешнее измерение 2 является фактором в аргументе malloc(), остальные измерения являются частью типа указателя и sizeof(*pool) правильно вычисляет размер одного трехмерного среза вашего 4D массива.

Размеры x, y, z do not должны быть постоянными времени компиляции. Они могут быть аргументами функции, локальными переменными, членами структуры, чем угодно. Их значение просто необходимо знать при объявлении указателя.

Это работает в C начиная с C99, но не работает в C ++ любого стандарта. C11 сделал эту функцию необязательной, чтобы упростить реализацию соответствующего компилятора для новых платформ, но большие наборы компиляторов предлагают полную поддержку этой функции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...