Как реализовать 2-мерный массив структур в C - PullRequest
11 голосов
/ 18 июля 2010

В настоящее время я пытаюсь понять, как реализовать двумерный массив struct в C. Мой код постоянно падает, и я действительно собираюсь позволить этому завершиться, как и все мои подходы, приводящие к C: garbage,Вот что я получил:

typedef struct {
    int i;
} test;

test* t[20][20];
*t = (test*) malloc(sizeof(test) * 20 * 20);

Моя славная ошибка:

ошибка: несовместимые типы при назначении типу "struct test * [20]" from type "struct test *'

Нужно ли выделять память отдельно для каждого второго измерения?Я схожу с ума.Это должно быть так просто.Однажды я соберу машину времени и намагничу несколько дискет c-compiler ...

Ответы [ 5 ]

23 голосов
/ 18 июля 2010

Этого должно быть достаточно:

typedef struct {
    int i;
} test;

test t[20][20];

Это объявит двумерный массив размером test размером 20 x 20. Нет необходимости использовать malloc.

ЕслиЕсли вы хотите динамически распределить ваш массив, вы можете сделать это:

// in a function of course
test **t = (test **)malloc(20 * sizeof(test *));
for (i = 0; i < 20; ++i)
    t[i] = (test *)malloc(20 * sizeof(test));
6 голосов
/ 18 июля 2010
test **t;

t = (test **)malloc(sizeof(test *) * 20);
for (i = 0; i < 20; i++) {
   t[i] = (test *)malloc(sizeof(test) * 20);
}
3 голосов
/ 18 июля 2010

Другие ответы показывают, как это исправить, но не объясняют почему.Как подсказал компилятор, тип t в вашем исходном примере на самом деле test *[20], поэтому вашего приведения к test * было недостаточно.

В C имя массива T измерения N фактически имеет тип *T[dim0][dim1]...[dimN-1].Fun.

1 голос
/ 18 июля 2010

Из моих наблюдений вы можете не знать точно, что вы хотите, и путать в арифметике структуры и указателя.Пожалуйста, просмотрите следующие 2 возможности.

1) Двумерный массив с каждым элементом имеет указатель на test.В этом случае память всех указателей на test с уже статически выделена .Но память реального test s не готова.В этом случае вы должны заполнить test [i][j] один за другим.

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

typedef struct {
    int i;
} test;

test* t[20][20]; 
/* or instead of statically allocated the memory of all the pointers to tests
   you can do the following to dynamically allocate the memory
   test ***t;
   t = (test***)malloc(sizeof(test *) * 20 * 20);
*/ 

for (int i=0; i < 20; i++){
   for (int j=0; j < 20; j++){
      t[i][j] = malloc(sizeof(test));
   }
}

2) Двумерный массив с каждым элементом представляет собойtest.В этом случае память всех test s уже выделена .Кроме того, память настоящих test s готова к использованию без дополнительной подготовки.

Все test непрерывны в памяти как большой блок и всегда находятся там.Это означает, что вы можете тратить часть памяти, если вам нужны все test с в определенное пиковое время, и большую часть времени вы используете только несколько из них.

typedef struct {
    int i;
} test;

test t[20][20]; 
/* or instead of statically allocated the memory of all tests
   you can do the following to dynamically allocate the memory
   test **t;
   t = (test**)malloc(sizeof(test) * 20 * 20);
*/ 
0 голосов
/ 18 июля 2010

Кроме того, до тех пор, пока размер вашего внутреннего измерения постоянен, вы можете выделить переменное количество отсчетов этого внутреннего измерения

int n = ...;
test (*t)[20] = malloc(sizeof (*t) * n);
t[0 .. (n-1)][0 .. 19] = ...;
...