Как задать двумерный динамический массив в c
Перейти к содержимому

Как задать двумерный динамический массив в c

  • автор:

Создание двумерного динамического массива

Как создать двумерный динамический массив так, чтобы можно было получать доступ как к статическому Array[a][b] ?

Отслеживать
218k 15 15 золотых знаков 117 117 серебряных знаков 229 229 бронзовых знаков
задан 15 дек 2011 в 13:10
1,287 12 12 золотых знаков 36 36 серебряных знаков 61 61 бронзовый знак

2 ответа 2

Сортировка: Сброс на вариант по умолчанию

Это тема здесь как-то уже поднималась. Но напишу еще раз. Создать массив int 10×20 Способ 1

const int x = 10, y = 20; int ** array = (int**) malloc (sizeof (int*) * x); for (int i = 0; i

Обращаться к элементам такого массива можно array[m][n]

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

int * array = (int*) malloc (sizeof(int)*x*y); 

Но обращаться к его элементy [m][n] можно только так:

int a = *(array + y*m + n); 

Отслеживать
ответ дан 15 дек 2011 в 13:19
23.9k 2 2 золотых знака 37 37 серебряных знаков 69 69 бронзовых знаков
неплохо) спасибо )
15 дек 2011 в 13:23

Кстати, массивы небольшого размера, который неизвестен во время компиляции, можно создавать и на стеке. Для этого нужно заменить malloc на alloca. И освобождать его не нужно. При возврате из функции он сам удалится.

15 дек 2011 в 16:07
угу. тоже правильно.
15 дек 2011 в 16:37

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

Итак, вариант — который нужен в общем-то только для совместимости с объявлением обычного массива type array[Rows][Cols] —

type * array = new type[Rows*Cols]; // C++ type * array = malloc(sizeof(type)*Rows*Cols); // C 

Освобождение памяти простейшее —

delete[] array; // C++ free(array); // C 

Плюс: совместимость по схеме размещения в памяти с обычным массивом. Минус: обращение array[r][c] не работает — только array[r*Cols+c] или *(array+r*Cols+c) .

Варианты, допускающие обращение array[r][c] — но сразу же предупреждение: несовместимы с размещением в памяти обычного массива. Легкий минус всех их — двойное косвенное обращение.

// C++ type ** array = new type*[Rows]; for(size_t i = 0; i < Rows; ++i) array[i] = new type[Cols]; . for(size_t i = 0; i < Rows; ++i) delete[] array[i]; delete[] array; // C type ** array = malloc(sizeof(type*)*Rows); for(size_t i = 0; i < Rows; ++i) array[i] = malloc(sizeof(type)*Cols); . for(size_t i = 0; i < Rows; ++i) free(array[i]); free(array); 

Обращение к элементам массива - array[r][c] .

Если немного подумать, то в варианте для С, где нет никаких конструкторов-деструкторов, можно упростить освобождение памяти:

// C type ** array = malloc(Rows*(sizeof(type*) + sizeof(type)*Cols)); for(size_t i = 0; i < Rows; ++i) array[i] = ((unsigned char*)array +sizeof(type*)*Rows+i*sizeof(type)*Cols); . free(array); 

Плюс один - очистка памяти в одно касание. Минусы - возможные проблемы выравнивания, возможная проблема strict aliasing. Как мне кажется, реально проявляться не должны, но тем не менее буду признателен тем, кто покажет, как строго избавиться от проблем при сохранении функциональности.

Впрочем. еще есть и плюс второй:

type * a = (type*)((unsigned char*)array +sizeof(type*)*Rows); 

совместим с массивом type a[Rows][Cols] по размещению в памяти. Так что с одним и тем же массивом можно работать и так, и эдак.

Еще одна экзотика - поскольку по указателю нельзя определить размеры массива.

Вот такой вариант кода, как приведено ниже, позволяет хранить размеры массива прямо в выделенном массиве (перед указателями). Проблема в том, что при этом из функции возвращается смещенный указатель, так что цена вопроса - в том, что удалять такой массив нужно только через свою функцию. Зато при передаче не нужны никакие дополнительные параметры 🙂

T** create(int N, int M) < T** arr = (T**)malloc(2*sizeof(int)+N*(sizeof(T*)+M*sizeof(T))); *((int*)arr) = N; *((int*)arr+1) = M; arr = (T**)((char*)arr+2*sizeof(int)); for(int i = N, ofs = N*sizeof(T*); i-->0; ofs += M*sizeof(T)) arr[i] = (T*)((char*)arr + ofs); return arr; > void kill(T** arr) < free((char*)arr-2*sizeof(int)); >int rows(T**arr) < return *(int*)((char*)arr-2*sizeof(int)); >int cols(T**arr)

Все это относится только к C, потому что в С++ этих проблем нет - просто берем и объявляем

vertor> array(Rows,vector(Cols)); 

после чего есть все - и обращение array[i][j] , и нужные размеры -

Rows == array.size() Cols == array[0].size() 

Нужно только следить, чтоб случайно не изменить размер какого-то из векторов.

Как задать двумерный динамический массив в c

Кроме отдельных динамических объектов в языке C++ мы можем использовать динамические массивы. Для выделения памяти под динамический массив также используется оператор new , после которого в квадратных скобках указывается, сколько массив будет содержать объектов:

int *numbers ; // динамический массив из 4 чисел // или так // int *numbers = new int[4];

Причем в этом случае оператор new также возвращает указатель на объект типа int - первый элемент в созданном массиве.

В данном случае определяется массив из четырех элементов типа int, но каждый из них имеет неопределенное значение. Однако мы также можем инициализировать массив значениями:

int *numbers1 >; // массив состоит из чисел 0, 0, 0, 0 int *numbers2 >; // массив состоит из чисел 1, 2, 3, 4 int *numbers3 >; // массив состоит из чисел 1, 2, 0, 0 // аналогичные определения массивов // int *numbers1 = new int[4]<>; // массив состоит из чисел 0, 0, 0, 0 // int *numbers1 = new int[4](); // массив состоит из чисел 0, 0, 0, 0 // int *numbers2 = new int[4]< 1, 2, 3, 4 >; // массив состоит из чисел 1, 2, 3, 4 // int *numbers3 = new int[4]< 1, 2 >; // массив состоит из чисел 1, 2, 0, 0

При инициализации массива конкретными значениями следует учитывать, что если значений в фигурных скобках больше чем длина массива, то оператор new потерпит неудачу и не сможет создать массив. Если переданных значений, наоборот, меньше, то элементы, для которых не предоставлены значения, инициализируются значением по умолчанию.

Стоит отметить, что в стандарт С++20 добавлена возможность выведения размера массива, поэтому, если применяется стандарт С++20, то можно не указывать длину массива:

int *numbers >; // массив состоит из чисел 1, 2, 3, 4

После создания динамического массива мы сможем с ним работать по полученному указателю, получать и изменять его элементы:

int *numbers >; // получение элементов через синтаксис массивов std::cout 

Причем для доступа к элементам динамического массива можно использовать как синтаксис массивов ( numbers[0] ), так и операцию разыменования ( *numbers )

Соответственно для перебора такого массива можно использовать различные способы:

unsigned n< 5 >; // размер массива int* p < new int[n] < 1, 2, 3, 4, 5 >>; // используем индексы for (unsigned i<>; i < n; i++) < std::cout std::cout ; i < n; i++) < std::cout std::cout ; q != p + n; q++) < std::cout std::cout 

Обратите внимание, что для задания размера динамического массива мы можем применять обычную переменную, а не константу, как в случае со стандартными массивами.

Для удаления динамического массива и освобождения его памяти применяется специальная форма оператора delete :

delete [] указатель_на_динамический_массив;

#include int main() < unsigned n< 5 >; // размер массива int* p < new int[n] < 1, 2, 3, 4, 5 >>; // используем индексы for (unsigned i<>; i < n; i++) < std::cout std::cout

Чтобы после освобождения памяти указатель не хранил старый адрес, также рекомендуется обнулить его:

delete [] p; p = nullptr; // обнуляем указатель

Многомерные массивы

Также мы можем создавать многомерные динамические массивы. Рассмотрим на примере двухмерных массивов. Что такое по сути двухмерный массив? Это набор массив массивов. Соответственно, чтобы создать динамический двухмерный массив, нам надо создать общий динамический массив указателей, а затем его элементы - вложенные динамические массивы. В общем случае это выглядит так:

#include int main() < unsigned rows = 3; // количество строк unsigned columns = 2; // количество столбцов int** numbers>; // выделяем память под двухмерный массив // выделяем память для вложенных массивов for (unsigned i<>; i < rows; i++) < numbers[i] = new int[columns]<>; > // удаление массивов for (unsigned i<>; i < rows; i++) < delete[] numbers[i]; >delete[] numbers; >

Вначале выделяем память для массива указателей (условно таблицы):

int** numbers>;

Затем в цикле выделяем память для каждого отдельного массива (условно строки таблицы):

numbers[i] = new int[columns]<>;

Освобождение памяти идет в обратном порядке - сначала освобождаем память для каждого отдельного вложенного массива, а затем для всего массива указателей.

Пример с вводом и выводом данных двухмерного динамического массива:

#include int main() < unsigned rows = 3; // количество строк unsigned columns = 2; // количество столбцов int** numbers>; // выделяем память под двухмерный массив for (unsigned i<>; i < rows; i++) < numbers[i] = new int[columns]<>; > // вводим данные для таблицы rows x columns for (unsigned i<>; i < rows; i++) < std::cout ; j < columns; j++) < std::cout > numbers[i][j]; > > // вывод данных for (unsigned i<>; i < rows; i++) < // выводим данные столбцов i-й строки for (unsigned j<>; j < columns; j++) < std::cout std::cout for (unsigned i<>; i < rows; i++) < delete[] numbers[i]; >delete[] numbers; >

Пример работы программы:

Enter data for 1 row 1 column: 2 2 column: 3 Enter data for 2 row 1 column: 4 2 column: 5 Enter data for 3 row 1 column: 6 2 column: 7 2 3 4 5 6 7

Указатель на массив

От типа int** , который представляет указатель на указатель (pointer-to-pointer) следует отличать ситуацию "указатель на массив" (pointer to array). Например:

#include int main() < unsigned n; // количество строк int (*a)[2] = new int[n][2]; int k<>; // устанавливаем значения for (unsigned i<>; i < n; i++) < // устанавливаем данные для столбцов i-й строки for (unsigned j<>; j < 2; j++) < a[i][j] = ++k; >> // вывод данных for (unsigned i<>; i < n; i++) < // выводим данные столбцов i-й строки for (unsigned j<>; j < 2; j++) < std::cout std::cout // удаляем данные delete[] a; a = nullptr; >

Здесь запись int (*a)[2] представляет указатель на массив из двух элементов типа int. Фактически мы можем работать с этим объектом как с двухмерным массивом (таблицей), только количество столбцов в данном случае фиксировано - 2. И память для такого массива выделяется один раз:

int (*a)[2] = new int[n][2];

То есть в данном случае мы имеем дело с таблице из n строк и 2 столцов. Используя два индекса (для строки и столца), можно обращаться к определенному элементу, установить или получить его значение. Консольный вывод данной программы:

1 2 3 4 5 6

Двумерный динамический массив

Создать двумерный массив (вводим матрицу с клавиатуры) если матрица квадратная то найти произведение под побочной диагонали матрицы, иначе найти модуль минимальный элемента матрицы если не понимаете объясню)) детально

int main() < int M ; int N ; int i, j; int** matrix; cin >> M; cin >> N; matrix = new int*[M]; for ( i = 0; i < M; i++) matrix[i] = new int[N]; for ( i = 0; i < M; i++) // ввод for ( j = 0; j < N; j++) < cout > matrix[i][j]; > cout cout

Вот вводим двумерный динамический массив а как посчитать ниже побочной матрицы диагональ напишите пожалуйста я как бы знаю как но в программе не могу написать это

Я вот читаю некоторые посты и просто охреневаю: написано то ли после доброго косяка, то ли после 0,5 на рыло.

(1) найти произведение под побочной диагонали матрицы
(2) как посчитать ниже побочной матрицы диагональ

И что тебе таки надо, Ангел за номером 143?

Макар вариант 1 и еще это задание дают учителя) а не мы сами придумываем я вот учусь на программиста знаю паскаль но нам дали задание сделать на си++ и я не знаю программу эту

Angel143, ты не находишь, что даже вариант 1 выглядит несколько странно, хотя догадаться, что там написано, можно. Я не думаю, что ваши учителя вам дают именно так сформулированное задание.

Отмаз как на Паскале — знаю, а на С++ — «сами мы не местные» — не прокатывает. Напиши рабочий вариант программы на Паскале, а на С++ перевести — не проблема, поможем.

Кстати кусок программы с вводом значений и распечаткой — вполне ничего себе. Только с форматированием кода сбился.

Маркат именно так и дают)) я могу написать код но я не знаю как цикл создать для нахождение произведение под побочной диагонали матрицы. Если напишешь то я сделаю сам прогу доделаю

здравствуйте ребята ! можете помочь
дано в массиве 100 элемент надо вывести на экран макс.

222, почитайте здесь

Angel143, не знаю кто тебе так дает, но от твоей орфографики я офигеваю.

Дальше — ни хрена не понял:

я могу написать код но я не знаю как цикл создать для нахождение произведение под побочной диагонали матрицы

Ты можешь написать код? или НЕ можешь? Хотя бы на Паскале. Видимо, «могу, но забыл как».

Лови кусок кода «для нахождение произведение под побочной диагонали матрицы», если я вообще понял, чего ты хочешь.

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

Как создать динамический двумерный массив

Как создать динамический двумерный массив и самому его заполнить?
Как создать динамический двумерный массив и самому его заполнить?

Используя malloc и realloc создать двумерный динамический массив
Используя malloc и realloc, помогите написать часть кода для ввода массива строк,количество строк и.

Создать двумерный динамический массив для переменных произвольного типа
это часть кода. сначала создал 2д массив для интов- все работало. но мне сказали сделать так чтобы.

Как задать двумерный динамический массив
Задание следующее нужно задать и заполнить двумерный массив размером 2хt. Пользователь вводит.

Регистрация: 02.01.2014
Сообщений: 60

1 2 3 4 5 6 7 8 9 10 11 12
// Создадим квадратный массив размера size int size, i; int** array = (int**)malloc(sizeof(int*) * size); for(i = 0; i  size; i++) array[i] = (int*)malloc(sizeof(int*) * size); //. Что-то поделаем с ним // Очистим память for(i = 0; i  size; i++) free(array[i]); free(array);

Регистрация: 22.09.2015
Сообщений: 173

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
#include #include int main() { int i, j; long long n, m; long long *ptr; scanf("%lld %lld", &n, &m); long long **array = (long long **) malloc(n * sizeof(long long*)); for (i = 0; i  n; i++) { array[i] = (long long **) malloc(m * sizeof(long long*)); } for(i = 0; i  n; i++) { for(j = 0; j  n; j++) { // Sto-to delaem } } for(i = 0; i  n; i++) { free(array[i]); } free(array); return 0; }

Почему у меня вылазит такое предупреждение?

warning: assignment from incompatible pointer type [enabled by default] array[i] = (long long **) malloc(m * sizeof(long long*));

Добавлено через 2 часа 25 минут

ЦитатаСообщение от Aliksan Посмотреть сообщение

long long **array = (long long **) malloc(n * sizeof(long long*)); for (i = 0; i < n; i++) < array[i] = (long long **) malloc(m * sizeof(long long*)); >
Сам же и нашел ошибку, так правильно:

1 2 3 4
long long **array = (long long **) malloc(n * sizeof(long long*)); for (i = 0; i  n; i++) { array[i] = (long long *) malloc(m * sizeof(long long)); }

Регистрация: 13.05.2020
Сообщений: 1

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
#define _CRT_SECURE_NO_WARNINGS #include #include #include int main() { int *a; // указатель на массив int i, j, n, m; system("chcp 1251"); system("cls"); printf("Введите количество строк: "); scanf("%d", &n); printf("Введите количество столбцов: "); scanf("%d", &m); // Выделение памяти a = (int*)malloc(n*m * sizeof(int)); // Ввод элементов массива for (i = 0; in; i++) // цикл по строкам { for (j = 0; jm; j++) // цикл по столбцам { printf("a[%d][%d] = ", i, j); scanf("%d", (a + i*m + j)); } } // Вывод элементов массива for (i = 0; in; i++) // цикл по строкам { for (j = 0; jm; j++) // цикл по столбцам { printf("%5d ", *(a + i*m + j)); // 5 знакомест под элемент массива } printf("\n"); } free(a); getchar(); getchar(); return 0; }

1980 / 1098 / 693
Регистрация: 25.04.2016
Сообщений: 3,119

Aliksan, не совсем, malloc может вернуть NULL в случае, если память по каким-то причинам не была выделена, и ваша программа должна на это как-то реагировать, например:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
#include #include int main (void)  n  1  int **array = (int **) malloc(sizeof(int *) * n); if (array == NULL) { // если память не дали fprintf(stderr, "Error allocate memory!\n"); return 2; } long long i; for (i = 0; i  n; i++) { array[i] = (int *) malloc(sizeof(int) * m); if (array[i] == NULL) { // если память не дали while (--i >= 0) { // освобождаем всю память, которую успели занять free(array[i]); } free(array); fprintf(stderr, "Error allocate memory!\n"); // сообщаем об ошибке return 2; // выходим из программы с кодом ошибки } } // Теперь можно работать с массивом long long j; for (i = 0; i  n; i++) { for (j = 0; j  m; j++) { array[i][j] = rand() %100; printf("%4d", array[i][j]); } puts(""); } // освобождаем память и выходим for(i = 0; i  n; i++) { free(array[i]); } free(array); return 0; }

==3437== Memcheck, a memory error detector
==3437== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==3437== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info

3 7
83 86 77 15 93 35 86
92 49 21 62 27 90 59
63 26 40 26 72 36 11

==3437== HEAP SUMMARY:
==3437== in use at exit: 0 bytes in 0 blocks
==3437== total heap usage: 6 allocs, 6 frees, 2,156 bytes allocated
==3437==
==3437== All heap blocks were freed -- no leaks are possible
==3437==
==3437== For lists of detected and suppressed errors, rerun with: -s
==3437== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Добавлено через 11 минут
Если обратить внимание на количество операций alloc в выводе валгринда. можно заметить, что на массив 3х7 понадобилось 4 таких операции. Есть другой способ, более экономичный:

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
#include #include #include int main (void)  srand( (unsigned)time(NULL)/2 ); /* узнаем размеры массива */ int rows, columns; printf(">> "); if (scanf("%d%d", &rows, &columns) != 2  /* запрашиваем память под массив */ float ** numbers = (float**) malloc(sizeof(float *) * rows); // ^^^ сначала создаем массив указателей на строки двумерного массива if (numbers == NULL) { // если память не дали fprintf(stderr, "Error allocate memory.\n"); // сообщаем об ошибке return 2; // выходим с кодом ошибки } numbers[0] = (float *) malloc(sizeof(float) * rows*columns); // ^^^ затем создаем одномерный массив для хранения данных if (numbers[0] == NULL) { fprintf(stderr, "Error allocate memory.\n"); free(numbers); // освобождаем память, которую уже успели занять return 2; } // и наконец, "пришиваем" соответствующие строки к указателям for (size_t i = 1; i  rows; i++) numbers[i] = numbers[i-1] + columns; /* заполняем массив случайными: */ int i, k; for (i = 0; i  rows; i++) for (k = 0; k  columns; k++) numbers[i][k] = rand() %5 + 1.0 / (1 + rand() %5); /* выводим элементы массива на экран */ for (i = 0; i  rows; i++) { for (k = 0; k  columns; k++) printf("%6.2lf", numbers[i][k]); puts(""); } /* освобождаем память и выходим */ free(numbers[0]); free(numbers); return 0; }

==3640== Memcheck, a memory error detector
==3640== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==3640== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info

>> 3 7
2.50 1.50 1.25 4.20 4.20 4.33 0.50
4.20 1.33 0.50 2.25 5.00 1.25 0.20
3.25 3.50 1.20 4.25 2.25 2.50 4.50

==3640== HEAP SUMMARY:
==3640== in use at exit: 0 bytes in 0 blocks
==3640== total heap usage: 4 allocs, 4 frees, 2,156 bytes allocated
==3640==
==3640== All heap blocks were freed -- no leaks are possible
==3640==
==3640== For lists of detected and suppressed errors, rerun with: -s
==3640== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Как видно, в этом случае требуется всего два обращения к памяти, что в два раза меньше. Самое приятное, что при любом размере массива нам всегда понадобится ровно два вызова malloc для запроса памяти под массив и ровно два free для освобождения этой памяти в конце программы.

На первый взгляд разница незначительная. Но предположим, что у нас есть двумерный массив, который хранит цвет каждого пикселя картинки 1920 х 1080.

Просто на то, чтобы создать такой массив первым способом, понадобится 1081 вызов malloc()
Вторым - по-прежнему всего 2.

87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
Помогаю со студенческими работами здесь

Как правильно объявить двумерный динамический массив через malloc
Подскажите как правильно объявить двумерный динамический массив через malloc типа инт размером.

Как правильно выделить память под двумерный динамический массив
подскажите как правильно выделить память под двумерный динамический массив?

Как создать динамический массив
помогите

Как создать динамический массив?
моя программа не присваивает элементам массива нужное значение что здесь неправильно?#include.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *