Как правильно выделить память для двумерного массива в структуре в C, если размеры массива неизвестны на этапе компиляции?
Я хочу создать структуру, один из членов которой является двумерным массивом, и чтобы эта структура размещалась в куче.
typedef struct Map
{
int xSize;
int ySize;
int mapMatrix[][];
} Map;
Мой IDE (VS Code с расширением C/C++ от Microsoft) говорит, что я не могу использовать массив с такими элементами. Я не знаю размеры массива на этапе компиляции, так что не могу обойти это ограничение, задав фиксированный размер.
Я подумал вместо этого использовать:
typedef struct Map
{
int xSize;
int ySize;
int *mapMatrix[]; // или, возможно, 'int **mapMatrix;'?
} Map;
но я не уверен, как правильно выделить память для этого массива (будет ли здесь больше накладных расходов за указатели по сравнению с типичным 2D массивом?). Также я хочу инициализировать память нулями, поэтому планирую использовать функцию calloc.
Когда вы работаете с динамическим выделением памяти для двумерных массивов в C, потребуется несколько шагов. Сначала давайте уточним, как правильно выделить и инициализировать память для вашей структуры Map, второй вариант с int **mapMatrix будет наиболее подходящим. Вот пошаговое руководство:
Определение структуры:
typedef struct Map
{
int xSize;
int ySize;
int **mapMatrix; // указатель на указатели, что позволяет создать "двумерный массив"
} Map;
Выделение памяти для структуры и инициализация массива:
#include <stdlib.h>
Map* createMap(int xSize, int ySize) {
// Выделяем память для структуры
Map *map = (Map*)malloc(sizeof(Map));
if (map == NULL) {
// Обработка ошибки недостатка памяти
return NULL;
}
map->xSize = xSize;
map->ySize = ySize;
// Выделяем память для строк (указателей)
map->mapMatrix = (int**)calloc(xSize, sizeof(int*));
if (map->mapMatrix == NULL) {
free(map); // Очищаем ранее выделенную память для структуры
return NULL;
}
// Выделяем память для каждого столбца и инициализируем нулями
for (int i = 0; i < xSize; i++) {
map->mapMatrix[i] = (int*)calloc(ySize, sizeof(int));
if (map->mapMatrix[i] == NULL) {
// Обработка ошибок и освобождение ранее выделенной памяти
for (int j = 0; j < i; j++) {
free(map->mapMatrix[j]);
}
free(map->mapMatrix);
free(map);
return NULL;
}
}
return map;
}
Освобождение памяти:
Когда вы закончите использовать карту, убедитесь, что вы освобождаете полученную память:
void freeMap(Map *map) {
if (map != NULL) {
for (int i = 0; i < map->xSize; i++) {
free(map->mapMatrix[i]);
}
free(map->mapMatrix);
free(map);
}
}
Этот подход позволяет вам иметь гибкость в динамическом выделении памяти для карт любой размерности. Да, использование указателей для строк и столбцов создает немного больше накладных расходов по сравнению с плотно упакованными массивами, но это стандартный способ работы с динамическими двумерными массивами в C, когда размеры неизвестны на этапе компиляции. Это также позволяет легко инициализировать массив нулями, используя calloc. . Я ответил на ваш вопрос?