Как передать двумерный массив в функцию 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++ кода. Единица трансляции
Передать двумерный статический массив в функцию
То есть передать можно, используя различные ухищрения, но скорей всего функция не будет работать так, как вы предполагаете.
Есть такой универсальный подход. Это интерпретировать любой двумерный массив, как одномерный, и передавать значения размеров каждой размерности массива.
void f( int a[], size_t m, size_t n ); //. int A[3][4]; f( reinterpret_cast( A ), 3, 4 );
Вот демонстрационная программа
#include #include void f( int a[], size_t m, size_t n ) < for ( size_t i = 0; i < m; i++ ) < for ( size_t j = 0; j < n; j++ ) a[i * n + j ] = i * n + j; >> int main() < const size_t M = 3; const size_t N = 4; int a[M][N]; f( reinterpret_cast( a ), M, N ); for ( size_t i = 0; i < M; i++ ) < for ( size_t j = 0; j < N; j++ ) std::cout return 0; >
Ее вывод на консоль
0 1 2 3 4 5 6 7 8 9 10 11
Если же писать программу на C, а не на C++, то там есть массивы переменной длины, и поэтому вам было бы проще.
В C++ для этих целей лучше использовать стандартный класс std::vector
std::vector> v( 3, std::vector( 4 ) );
Что касается вашего вопроса
2)Статические 2D массивы хранятся в памяти линейно. Динамические хранятся тоже линейно или нет?
то если вы будете распределять его в памяти как двумерный массив, то естественно его элементы будут храниться линейно по строкам. Например
int ( *a )[4] = new int[3][4];
А что касается этого вопроса
3)Какую связь имеет статический 2D массив с указателями?
то любой массив в выражениях (за редким исключением) неявно преобразуется в указатель на свой первый элемент.
Отслеживать
ответ дан 6 ноя 2015 в 19:03
Vlad from Moscow Vlad from Moscow
44.8k 3 3 золотых знака 38 38 серебряных знаков 89 89 бронзовых знаков
А как сделать эту функцию универсальнее, чтобы она принимала любые A[x][y] ?
6 ноя 2015 в 19:08
@neko69 Что значит «любые»? Если любые двумерные массивы с любыми значениями размерностей, то сделайте ее шаблонной.
6 ноя 2015 в 19:10
Шаблонная, в смысле template
6 ноя 2015 в 19:12
@neko69 Если вы хотите иметь дело именно с двумерными массивами, то без этого не обойтись.
6 ноя 2015 в 19:13
@neko69 Смотрите мой обновленный ответ.
6 ноя 2015 в 19:17
В gcc сделать это совсем просто.
Вы можете передавать в функцию размерности матрицы (достаточно только «низших») и обращаться к элементам по индексам естестственным образом. Например:
void func (int n_lines, int n_columns, int array[][n_columns])
К сожалению g++ (и c++) не поддерживает такую передачу матриц в функцию. Поэтому проще всего (обладая знанием, что все элементы матрицы располагаются в памяти последовательно, сначала первая строка, за ней вторая и т.д.) передать в функцию адрес первого элемента матрицы, а в функции рассматривать ее как одномерный массив.
Естественно, пересчитывать индексы придется самому.
Вот пример файла, в котором представлены обе версии программы и результаты его запуска:
avp@avp-ubu1:hashcode$ cat c1.c #include #ifdef __cplusplus #include #endif static int aa[4][3] = < , , , >; #ifdef __cplusplus void func_matrix (int n, int m, int *x) < x[0] = x[(n - 1) * m + m - 1]; for (int i = 0; i < n; i++) for (int j = 0; j < m || !puts(""); j++) std::cout #else void func_matrix (int n, int m, int x[n][m]) < int i, j; x[0][0] = x[n - 1][m - 1]; for (i = 0; i < n; i++) for (j = 0; j < m || !puts(""); j++) printf("%d ", x[i][j]); >#endif int main (int ac, char *av[]) < #ifdef __cplusplus func_matrix(4, 3, &aa[0][0]); #else func_matrix(4, 3, aa); #endif >avp@avp-ubu1:hashcode$ gcc c1.c && ./a.out 43 12 13 21 22 23 31 32 33 41 42 43 avp@avp-ubu1:hashcode$ g++ c1.c && ./a.out 43 12 13 21 22 23 31 32 33 41 42 43 avp@avp-ubu1:hashcode$
Если вопросы еще остались, задавайте.
UPD
Вот вариант с указателями на строки «плотной» матрицы.
Берем статическую матрицу, делаем для нее массив указателей, передаем его в функцию транспонирования, которая делает в динамической памяти «плотную» транспонированную матрицу и возвращает новый массив указателей на ее строки.
#include #include int ** make_lines_ptrs (int *mx, int a, int b) < int **p = (int **)malloc(a * sizeof(int *)); for (int i = 0; i < a; i++) p[i] = mx + i * b; return p; >int ** transp (const int * const * m, int a, int b) < int *mx = (int *)malloc(a * b * sizeof(int)); for (int i = 0; i < a; i++) for (int j = 0; j < b; j++) mx[j * a + i] = m[i][j]; return make_lines_ptrs(mx, b, a); >void pri_mx (const int * const * m, int a, int b) < for (int i = 0; i < a; i++) for (int j = 0; j < b || !puts(""); j++) printf("%d ", m[i][j]); >static int aa[4][3] = < , , , >; int main (int ac, char *av[])
Ну, память перед выходом Вы уж сами освободите?
Как передать в функцию двумерный массив.
В одной из статей, написанной несколько лет назад, описывал для чего в си используются указатели и как с ними работать. Сегодня перечитывая, ту статью понял, что есть еще один интересный вопрос, который стоило бы рассмотреть. «Как передать в функцию двумерный массив ?«
Ответ напрашивается сам собой, использовать для этого указатель. Но просто передать адрес первого элемента двумерного массива недостаточно(по сути указатель), давайте разберемся почему.
Несмотря на то, что двумерный массив, по сути представляет собой таблицу(массив элементами которого являются массивы), в памяти все его элементы хранятся последовательно и для того, чтобы в этой последовательности как-то ориентироваться необходимо знать размер его второй мерности. То есть если у нас есть массив arr[5][20], для работы с ним достаточно знать с какого адреса он начинается и что размер его второй мерности равен 20.
Тогда формула для вычисления адреса любого элемента массива будет иметь следующий вид
arr + 20*i + j
arr — адрес начала массива;
i — первый индекс элемента;
j — второй индекс элемента;
Двумерный массив можно использовать для хранения строк, описывающих какую-то сущность. В таком случае функция, модифицирующая его, будет выглядеть следующим образом.
void Update_List_Name(char *arr, uint8_t j) { char a; uint32_t adr; //первая буква первой строки имеет адрес начала массива adr = (arr+0*j+0); //вторая буква первой строки располагается по адресу adr = (arr+0*j+1) ; //вторая буква первой строки располагается по адресу adr = (arr+1*j+0) ; //вторая буква первой строки располагается по адресу adr = (arr+1*j+1) // для получения данных хранящихся в ячейке, // необходимо использовать операцию разыменования a = *adr; >
Аналогично можно передать указатель, указав размер второй мерности массива
void Update_List_Name(char *arr[20]) { char a; //в таком случае обращаться к элементам массива можно как обычно a = arr[1][2]; >
Или передать массив, указав размер его второй мерности.
void Update_List_Name(char arr[][20]) { char a; //в таком случае обращаться к элементам массива можно как обычно a = arr[1][2]; >
Какой способ из вышеприведенных использовать каждый решает сам, когда есть понимание сути, это не имеет большого значения.
Как передать двумерный массив в функцию c
Сообщений: 48
Передача двумерного массива в функцию
До последнего времени для передачи двумерного массива в функцию пользовался следующими вариантами
Вар1:
#include using std::cout; using std::cin; void funArray(int mass[][6], const int nstr, const int nstb); int main() < int Arr[5][6]=< , , , , >; funArray(Arr,5,6); cin.get(); cin.get(); return 0; > void funArray(int mass[][6], const int nstr, const int nstb) < for(int i=0; i>
Для динамических массивов использую Вариант2:
#include using std::cout; using std::cin; void funArray(int **mass, const int nstr, const int nstb); int main() < //ввод размера динамического двумерного массива: int N, M; cin >>N>>M; //выделение места в памяти под динамический двумерный массив: int **Arr=new int* [N]; for(int i=0; i>Arr[i][j]; //передача массива в функцию: funArray(Arr,N,M); cin.get(); cin.get(); return 0; > void funArray(int **mass, const int nstr, const int nstb) < for(int i=0; i>
А вот почему не работает следующий код, никак не могу понять. Можете объяснить, что не так?
#include using std::cout; using std::cin; void funArray(int *mass, const int nstr, const int nstb); int main() < int Arr[5][6]=< , , , , >; funArray(&Arr,5,6); cin.get(); cin.get(); return 0; > void funArray(int *mass, const int nstr, const int nstb)
Последний раз редактировалось FelixXXI; 27.08.2011 в 17:06 .