Куча выделяет 2D-массив (не массив указателей)
Я пишу C-код, и я бы хотел, чтобы heap выделил 512 * 256 байт. Для моего удобства я хотел бы иметь доступ к элементам с синтаксическим массивом [a] [b]; нет арифметики, чтобы найти правильный индекс.
Каждый учебник, который я вижу в Интернете, подсказывает мне создать массив указателей, которые указывают на массивы строк, которые я хочу в моем массиве. Это означает, что каждый подмассив должен быть malloc'd и free'd индивидуально. Меня интересует решение, для которого требуется только один вызов malloc и один вызов на бесплатный. (Таким образом, все элементы смежны) Я думаю, что это возможно, потому что я не буду создавать зубчатый массив.
Я был бы признателен, если бы кто-нибудь мог использовать синтаксис для объявления такого массива.
Ответы
Ответ 1
Ну, если вы хотите выделить массив типа, вы назначаете его в указатель этого типа.
Так как 2D-массивы представляют собой массивы массивов (в вашем случае массив из 512 массивов из 256 символов), вы должны назначить его в указатель на массив из 256 символов:
char (*arr)[256]=malloc(512*256);
//Now, you can, for example:
arr[500][200]=75;
(Скобки вокруг *arr
должны сделать его указателем на массив, а не массив указателей)
Ответ 2
Если вы выделяете такой массив, для этого требуется два вызова free
, но он позволяет синтаксис стиля array[a][b]
и является непрерывным.
char **array = malloc(512 * sizeof(char *));
array[0] = malloc(512*256);
for (int i = 1; i < 512; i++)
array[i] = array[0] + (256 * i);
См. array2
здесь для получения дополнительной информации: http://c-faq.com/aryptr/dynmuldimary.html
Ответ 3
Это легко предположить, что вам не нужна совместимость с древним стандартом C89 (среди текущих компиляторов C только для MSVC и нескольких встроенных компиляторов). Вот как вы это делаете:
int (*array)[cols] = malloc(rows * sizeof *array);
Тогда array[a][b]
справедливо для любого a
в [0,rows)
и b
в [0,cols)
.
В языке стандарта C array
имеет измененный тип. Если вы хотите передать указатель на другие функции, вам нужно будет повторить этот тип в списке аргументов функции и убедиться, что по меньшей мере число столбцов передается функции (так как это необходимо как часть измененного с изменением тип).
Изменить: Я пропустил тот факт, что OP заботится только о фиксированном размере 512x256. В этом случае C89 будет достаточным, и все, что вам нужно, это:
int (*array)[256] = malloc(512 * sizeof *array);
Точный же тип может использоваться в списках аргументов функции, если вам нужно передать указатель между функциями (а также как возвращаемый тип функции, но для этого использования вам может понадобиться typedef it...: -)
Ответ 4
Поскольку вы знаете размер массива загодя, вы можете создать тип struct
, содержащий массив 521x256, а затем динамически выделить struct
.
Ответ 5
Если вы знаете размер массива, вы можете typedef
его и сделать указатель на него. Вот короткий фрагмент, демонстрирующий это использование:
#include <stdio.h>
#include <stdlib.h>
typedef int array2d[20][20];
int main() {
int i,j;
array2d *a = malloc(sizeof(array2d));
for(i=0;i!=20;i++)
for(j=0;j!=20;j++)
(*a)[i][j] = i + j;
for(i=0;i!=20;i++)
for(j=0;j!=20;j++)
printf("%d ",(*a)[i][j]);
free(a);
return 0;
}
Ответ 6
Можно динамически выделять один и тот же тип многомерного массива, который
static char x[512][256];
дает вам, но это довольно сложно из-за распада типа. Я знаю только, как это сделать с помощью typedef
:
typedef char row[512];
row *x = malloc(sizeof(row) * 256);
Это позволяет определить размер второго измерения во время выполнения. Если оба измерения могут меняться во время выполнения, вам нужен вектор допинга.