Лучший способ справиться с распределением памяти для 2D-вещей, если он большой, это сделать что-то вроде этого:
// small fix to this, added pointer de-reference
// if you iterate over x in your outer loop you should
// change the index part to (a)->h*(x) + (y)
// but only do one or the other
#define IDX_DBL2D(a, x, y) (*((a)->d[(a)->w*(y) + (x)]))
struct dbl2d {int w,h; double[] d; };
struct dbl2d *alloc_2d_dbl(int w, int h) {
struct dbl2d *r = malloc(sizeof(struct dbl2d) + sizeof(double)*w*h);
r->w = w, r->h = h;
return r;
}
это похоже на то, что делает компилятор, когда вы объявляете 2d-массив (но он будет иметь индексы наоборот)
Это будет использовать меньше памяти (не нужно хранить все эти указатели строк) и хранить все вместе
Когда компилятор создает 2d массив фиксированного размера, он знает, насколько он велик, поэтому если вы пишете bar = foo[x][y];
, а foo равно nxm, то компилятор превращает это в bar = *(foo + x*m + y)
, однако это работает только для вещей, для которых компилятор знает какова форма вашего массива, поэтому то, что я определил выше, это в основном массив, который несет в себе его размеры.
Расчет индекса работает, так как если вы думаете о foo как о массиве массивов, то каждая строка имеет размер sizeof(*foo)*width
(в зависимости от погоды вы делаете x или y первой координатой, здесь я использую x, так как я привык к изображения, и это соглашение используется там), так что если вы умножаете свою координату y на количество элементов в строке, пропуская строки 'y', то вы можете получить элемент в строке, добавив x.
Пример использования:
void populateUserFeatureP(struct dbl2d *userFeatureP)
{
int x,y;
for(x = 0; x < CUSTOMERS; x++)
{
for(y = 0; y < FEATURES; y++)
{
IDX_DBL2D(userFeatureP, x, y) = 0;
}
}
}
void populateItemFeatureQ(struct dbl2d *itemFeatureQ)
{
int x,y;
for(x = 0; x < FEATURES; x++)
{
for(y = 0; y < MOVIES; y++)
{
printf("(%d,%d)\n", x, y);
IDX_DBL2D(itemFeatureQ, x, y) = 0;
}
}
}
int main(int argc, char *argv[]){
struct dbl2d *userFeatureP = alloc_2d_dbl(480189, 40);
struct dbl2d *itemFeatureQ = alloc_2d_dbl(40, 17770);
populateItemFeatureQ(itemFeatureQ);
populateUserFeatureP(userFeatureP);
return 0;
}