Функции в C++ для начинающих Передача в функцию двумерного динамического массива
Иногда возникает вопрос по работе массивов и функций. Многие испытывают проблемы при создании двумерного динамического массива для последующей его обработки с помощью функций. Найти информацию решения таких задач на момент написания статьи не так уж и просто. Да, описаны варианты создания, но лично я находил или простое создание двумерного динамического массива внутри main () или выделение памяти для массива непосредственно внутри принимающей его функции. Мне это очень не нравилось
Код С++ Создание динамического двумерного массива и обработка его с помощью функций
// Отображение массива
void ArrayShow (int ** A ,int N ,int M )
cout
for (int i = 0 ; i < N ; i ++)
for (int j = 0 ; j < M ; j ++)
if (!( j % M )) cout //Чтобы массив выглядел как массив
cout //Табуляция символов
// Инициализация массива случайными значениями
void ArrayInit (int ** A ,int N ,int M )
srand ( time ( 0 ));
for (int i = 0 ; i < N ; i ++)
for (int j = 0 ; j < M ; j ++)
A [ i ][ j ]= rand ()%( 100 )- 50 ; //Случайное значение в очередную ячейку массива
void main ()
clrscr ();
int ** A ; //Для создания двумерного массива удобен указатель на указатель
int N , M ; //Число колонок=N, Число строк= M
cin >> N >> M ; //Ввели размерность массива
// for ( int k=0; k<10;k++) Может кому нужно циклом
/* Создание динамического двумерного массива */
A =new int*[ N ];
for (int i = 0 ; i < N ; i ++) A [ i ]=new int[ M ];
ArrayInit ( A , N , M ); //Функция создания массива
ArrayShow ( A , N , M ); //Функция обработки массива
/*Очистка памяти от созданного двумерного массива*/
for ( i = 0 ; i < N ; i ++) delete [] A [ i ];
delete [] A ;
A = NULL ;
//> окончание цикла for
getch ();
return;
Не могу сильно и всё комментировать, потому что не обладаю глубокими знаниями. Это немного переделанный пример того, что я находил по передаче двумерного массива в функцию. По мне такие примеры, где массив создается непосредственно внутри функции или для него выделяется память внутри принимающей его функции не есть грамотное решение вопроса темы, поэтому пришлось переделывать на свой лад
Для того чтобы создать двумерный динамический массив, был использован указатель на указатель. Для решения обычных задач необязательно вникать в суть указателя и достаточно посмотреть, как указатели тут используются. Вообще что такое указатели, зачем они нужны, их недостатки и их преимущества любой уважающий себя программист наверняка знает, а, значит, если решили научиться программировать, то тоже должны изучить.
При написании приведенной программы, ячейки для двумерного массива были динамически созданы внутри функции main () Сразу же был дописан код очистки памяти от создаваемого массива. Если написать не сразу, то потом легко запутаться или забыть. Очистка памяти нужна только и только тогда когда массив больше не нужен . Между кусками кода выделения памяти под двумерный массив и очистки от него памяти был написан вызов двух функций. Первая функция принимает двумерный массив в качестве аргумента. Благодаря тому, что принимаемый параметр является указателем, то любые изменения массива внутри функции, влияют на этот массив вне функции напрямую (Передали на обработку -> Получили обновленный) . Нужно заполнить массив значениями. Чтобы заполнить массив значениями, нужно знать его размерность. Чтобы функция занесения данных в двумерный динамический массив знала размерность, туда были переданы эти данные. Осталось только использовать ввод данных с помощью циклов. Не думаю, что по этим циклам должны возникнуть вопросы. Функция маленькая и удобочитаемая. Главное понимать, что
Передавая двумерный массив, в функции можно принять указатель на указатель массива и указать число строк и колонок внутри массива .
Следующая функция принимает динамический массив как обычный двумерный. Чтобы массив принялся в таком виде, в котором был только что создан, обязательно принимающую его функцию вызывать до очистки памяти от нужного массива. По принимаемым параметрам эта функция похожа на ту, которая создавала двумерный массив. Используется указатель на указатель, и указываются данные размерности. Чтобы массив был не в одну строчку, была произведена проверка деления числа нацело. Если кто-то использует другие способы приведения массива к хорошему виду, то легко можно использовать удобные ему. Чтобы элементы массива не слились воедино, был использован элемент табуляции.
В качестве эксперимента была попытка реализовать создание динамического двумерного массива внутри цикла, потом передать этот массив в функции. Этот момент комментирован, но может оказаться кому-то полезным.
Главное четко осознавать
- если выделили память, то обязательно нужно её удалять.
- Удалять память нужно только и только тогда, когда динамически созданный массив больше реально не нужен
- Для передачи двумерного динамического массива в функцию удобно использовать указатель на указатель и при передаче его в функцию, в функцию стоит передавать размерность массива
Как передать двумерный динамический массив в функцию c
Как сделать передачу двумерного массива через параметр функции?
Либо создаёшь массив динамически:
Тогда можно написать функцию:
и использовать её прямо: f(arr);
Если же твой двумерный массив статический, то тебе обязательно нужно в объявлении функции указать одну (вторую) размерность:
Вот она, моя функция:
float det(float p[][], int n)
else add[х-1][y-1] = p[y][х];
det += p[i][0]*det(add, n-1))
Попытался перевести на указатели, получилось вот что:
float det(float **p, int n)
for(int i=0; int m=n>i; i++)
float **add = new float*[n-1];
else add[х-1][y-1] = p[y][х];
static float det;
det += p[i][0]*det(add, n-1); // вот здесь ошибка, не хочет вызываться [C++ Error] Call of nonfunction
А ещё можно ли как-нибудь за счёт параметра n указать сразу в параметре массива его размерность типа (n, m[n][n]).
void func(char mas[10][5]);
Ну, какие есть замечания:
1) Зачем тебе две переменных det — одна static, другая auto ??
2) Почему переменная det называется так же, как и функция? Или в латинском алфавите букв мало 😕 Тогда используй знак подчёркивания и цифры (цифры — не в начале). Компилятор, собственно, на это и ругается.
3) Если ты выделил память под переменную с помощью оператора new, то, когда она больше не нужна, освободи ресурс оператором delete. Пример
int* pa = new int;
Используй оператор delete[] для освобождения памяти для целого массива. Для двумерного массива это будет выглядеть так:
float **add = new float*[n-1];
add[i] = new float[n-1];
- Стандарт языка программирования Си
- Передача параметра в функцию по указателю в C стиле
- Передача параметров в функцию по указателю (C стиль) и по ссылке (C++ стиль)
- Передача структуры в функцию и изменение значений элементов структуры
- В чем разница объявления строки как массива и как указателя
- Использование очень больших чисел
- getch() в Linux
- Аргументы функции main()
- Как побайтно считать файл
- Реализация циклического сдвига ROR и ROL
- Динамическая загрузка библиотек в Linux
- Функция fmemopen() — открытие набора байт как файла в памяти с получением файлового дескриптора
- Подмена дефайнов (#define)
- Успешной отладки, шутка
- Как описывать функции с аргументами по-умолчанию в C/C++
- Форматированный вывод через функцию printf
- Создание и удаления двухмерного и трехмерного динамического массива
- Как передать в функцию двумерный массив, размер которого известен
- Как передать в функцию динамический двумерный массив
- Как правильно читать объявления в Си
- Вычисление pbkdf2 на языке C
- Определение разрядности платформы 32 или 64 бит
- Функции getuid() и geteuid()
- Указатели и символьные строки в языке C
- Практическое применение LD_PRELOAD или замещение функций в Linux
- Проблемы C-подобных языков. Где находиться типу: справа или слева? (Теория)
- Откуда в языке Си появился синтаксис указателей, и для чего он предназначался изначально
- Как в языке Си вызвать функцию, для которой известен адрес вызова в виде числа
- Вызов функции по известному адресу в языке Си — абстрактный тип данных указателя на функцию
- Структуры в языке Си. Определения структур в сравнении с языком C++
- Структуры в языке Си. Указатели на структуры
- Структуры в языке Си. Массивы структур
- Операция запятая «,» в языке Си и Си++
- Самый быстрый и оптимальный способ копирования строк в Cи и C++
- Стоит запомнить: цикл for в языке Си/Си++ — это цикл с предусловием
- Как происходит компиляция C/C++ кода. Единица трансляции
Как передать двумерный динамический массив в функцию c
Передать статический двумерный массив в функцию так, чтобы можно было получать доступ к его элементам через синтаксис a[x][y] можно только используя технику динамических массивов.
Однако есть более простой способ доступа к данным массива путем передачи указателя на первый элемент двумерного массива. При этом двумерный массив внутри функции будет выглядеть как одномерный массив указателей на одномерные массивы, и доступ к элементам нужно осуществлять с помощью конструкции [y*размерность_x+x].
Вот первый пример, как можно передавать двумерный массив:
void fun(int **array, int sizey, int sizex)
value=p_array[ y * sizex + x ]; // [ x ][ y ]
fun((int**)table, 5, 4);
Как видно, синтаксис неудобен, и внутри функции fun() для доступа к элементам используется создание дополнительного указателя.
Есть более простой вариант для передачи двумерных массивов, размер которых заранее известен:
#define TABLE_SIZE_X 5
#define TABLE_SIZE_Y 4
Передача динамического массива в функцию выполняется другими методами.
- Стандарт языка программирования Си
- Передача параметра в функцию по указателю в C стиле
- Передача параметров в функцию по указателю (C стиль) и по ссылке (C++ стиль)
- Передача структуры в функцию и изменение значений элементов структуры
- В чем разница объявления строки как массива и как указателя
- Использование очень больших чисел
- getch() в Linux
- Аргументы функции main()
- Как побайтно считать файл
- Реализация циклического сдвига ROR и ROL
- Динамическая загрузка библиотек в Linux
- Функция fmemopen() — открытие набора байт как файла в памяти с получением файлового дескриптора
- Подмена дефайнов (#define)
- Успешной отладки, шутка
- Как описывать функции с аргументами по-умолчанию в C/C++
- Форматированный вывод через функцию printf
- Создание и удаления двухмерного и трехмерного динамического массива
- Как передать в функцию двумерный массив, размер которого известен
- Как передать в функцию динамический двумерный массив
- Как правильно читать объявления в Си
- Вычисление pbkdf2 на языке C
- Определение разрядности платформы 32 или 64 бит
- Функции getuid() и geteuid()
- Указатели и символьные строки в языке C
- Практическое применение LD_PRELOAD или замещение функций в Linux
- Проблемы C-подобных языков. Где находиться типу: справа или слева? (Теория)
- Откуда в языке Си появился синтаксис указателей, и для чего он предназначался изначально
- Как в языке Си вызвать функцию, для которой известен адрес вызова в виде числа
- Вызов функции по известному адресу в языке Си — абстрактный тип данных указателя на функцию
- Структуры в языке Си. Определения структур в сравнении с языком C++
- Структуры в языке Си. Указатели на структуры
- Структуры в языке Си. Массивы структур
- Операция запятая «,» в языке Си и Си++
- Самый быстрый и оптимальный способ копирования строк в Cи и C++
- Стоит запомнить: цикл for в языке Си/Си++ — это цикл с предусловием
- Как происходит компиляция C/C++ кода. Единица трансляции
Динамические двумерные массивы
Динамические двумерные массивы в языке Си имеют сложный способ представления в памяти компьютера.
Рассмотрим одномерный массив из 10 указателей на объекты типа int:
A представляет собой указатель на указатель на int.
Кроме того, массив указателей может быть не статическим, а динамическим:
Следующий шаг сделать очень просто — по указателям, хранящимся в массиве A могут лежать не по одному значению, а по одномерному динамическому массиву таких значений.

Передача динамических двумерных массивов в функцию
Динамические массивы передаются в функции по-другому, передается указатель на начало массива указателей, а длина строки и количество строк вообще нигде не фигурируют. Контроль за границами массивов лежит полностью на программисте, поэтому, вероятно, стоит передавать в функцию отдельными параметрами размеры массива — количество строк и столбцов.
Пример работы с динамическим двумерным массивом
#include
#include
#define MATRIX_HEIGHT 4
#define MATRIX_WIDTH 5
void dynamic_array_print(int **A, size_t N, size_t M)
for(int i = 0; i < N; i++) for(int j = 0; j < M; j++) printf("%*d", 5, A[i][j]);
>
printf(«\n»);
>
>
/*
return pointer on 2d dynamic array
!allocates memory -> to be freed later
*/
int ** dynamic_array_alloc(size_t N, size_t M)
int **A = (int **)malloc(N*sizeof(int *));
for(int i = 0; i < N; i++) A[i] = (int *)malloc(M*sizeof(int));
>
return A;
>
void dynamic_array_free(int **A, size_t N)
for(int i = 0; i < N; i++) free(A[i]);
>
free(A);
>
void dynamic_array_test(size_t N, size_t M)
int **A = dynamic_array_alloc(N, M);
int x = 1;
for(int i = 0; i < N; i++) for(int j = 0; j < M; j++) A[i][j] = x;
x += 1;
>
>
dynamic_array_print(A, N, M);
/*memory investigation*/
printf(«\n Pointers to lines: «);
for(int **p = A; p < A + 3; p++)
printf(«%10d», (long int)*p);
printf(«\n Direct memory access (dangerous. ):\n»);
for(int *p = (int*)*A; p < (int*)*A + 25; p++)
printf(«%d\t», *p);
dynamic_array_free(A, N);
>
int main()
dynamic_array_test(MATRIX_HEIGHT, MATRIX_WIDTH);
return 0;
>
Выделение памяти под динамический массив
Как видно из примера, создание такой сложной структуры как двумерный динамический массив требует множества системных вызовов по выделению памяти:
int **A = (int **)malloc(N*sizeof(int *));
for(int i = 0; i < N; i++) A[i] = (int *)malloc(M*sizeof(int));
>
При таком выделении памяти нельзя просто взять, и освободить память по адресу A, т.к. будет возникать утечка памяти.
Правильное очищение таково:
for(int i = 0; i < N; i++) <
free(A[i]);
>
free(A);
Альтернатива такова: при некотором владении адресной арифметикой можно выделить память сразу для всех одномерных массивов, необходимых для организации двумерного динамического массива:
int ** A = malloc(n*sizeof(int*) + n*m*sizeof(int));
char * pc = A;
pc += n*sizeof(int*);
for (int i=0; i A[i] = pc + i*sizeof(m*sizeof(int));
Тогда освобождение памяти будет происходить очень легко: