Как передать двумерный массив в функцию 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++ кода. Единица трансляции

Как передать двумерный массив в функцию c

Если функция принимает в качестве параметра массив, то фактически в эту функцию передается указатель на первый элемент массива. То есть как и в случае с указателями нам доступен адрес, по которому мы можем менять значения. Поэтому следующие объявления функции будут по сути равноценны:

void print(int numbers[]); void print(int *numbers);

Передадим в функцию массив:

#include void print(int[]); int main() < int nums[] ; print(nums); > void print(int numbers[]) < std::cout 

В данном случае функция print выводит на консоль первый элемент массива.

Теперь определим параметр как указатель:

#include void print(int*); int main() < int nums[] ; print(nums); > void print(int *numbers)

Здесь также в функцию передается массив, однако параметр представляет указатель на первый элемент массива.

Ограничения

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

void print(int numbers[]) < int size = sizeof(numbers) / sizeof(numbers[0]); // или так // size_t size = std::size(nums); std::cout

И также мы не сможем использовать цикл for для перебора этого массива:

void print(int numbers[])

Передача маркера конца массива

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

Первый подход заключается в том, чтобы один из элементов массива сам сигнализировал о его окончании. В частности, массив символов может представлять строку - набор символов, который завершается нулевым символом '\0'. Фактически нулевой символ служит признком окончания символьного массива:

#include void print(char[]); int main() < char chars[] ; print(chars); > void print(char chars[]) < for (unsigned i<>; chars[i] != '\0'; i++) < std::cout >

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

#include void print(int[], size_t); int main() < int nums[]; size_t n ; print(nums, n); > void print(int numbers[], size_t n) < for(size_t i <>; i < n; i++) < std::cout >

Третий подход заключается в передаче указателя на конец массива. Можно вручную вычислять указатель на конец массива. А можно использовать встроенные библиотечные функции std::begin() и std::end() :

int nums[] < 1, 2, 3, 4, 5 >; int *begin ; // указатель на начало массива int *end ; // указатель на конец массива

Причем end возвращает указатель не на последний элемент, а адрес за последним элементом в массиве.

Применим данные функции:

#include void print(int*, int*); int main() < int nums[] < 1, 2, 3, 4, 5 >; int *begin ; int *end ; print(begin, end); > void print(int *begin, int *end) < for (int *ptr ; ptr != end; ptr++) < std::cout >

Константные массивы

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

#include void print(const int*, const size_t); void twice(int*, const size_t); int main() < int numbers[]; size_t n = std::size(numbers); print(numbers, n); twice(numbers, n); // увеличиваем элементы массива в два раза print(numbers, n); > void print(const int numbers[], const size_t n) < for(size_t i <>; i < n; i++) < std::cout std::cout void twice(int *numbers, const size_t n) < for(size_t i <>; i < n; i++) < numbers[i] = numbers[i] * 2; >>

В данном случае функция print просто выводит значения из массива, поэтому параметры этой функции помечаются как константные.

Функция twice изменяет элементы массива - увеличивает их в два раза, поэтому в этой функции параметр-массив является неконстантным. Причем поле выполнения функции twice массив numbers будет изменен.

Консольный вывод программы:

1 2 3 4 5 2 4 6 8 10

Передача массив по ссылке

Еще один сценарий передачи массива в функцию представляет передача массива по ссылке. Прототип функции, которая принимает массив по ссылке, выглядит следующим образом:

void print(int (&)[]);

Обратите внимание на скобки в записи (&) . Они указывают именно на то, что массив передается по ссылке. Пример использования:

#include void print(int (&)[], size_t); int main() < int nums[] ; size_t count = std::size(nums); print(nums, count); > void print(int (&numbers)[], size_t count) < for(size_t i<>; i < count; i++) < std::cout >

Подобным образом можпо передавать константные ссылки на массивы.

void print(const int (&)[]);

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

#include void print(const int (&)[5]); // массив строго с 5 элементами int main() < int nums1[] ; print(nums1); > void print(const int (&numbers)[5]) < for(unsigned i<>; i < 5; i++) < std::cout >

Здесь функция print принимает ссылку строго на массив с 5 элементами. И поскольку мы знаем точный размер массива, то нам нет необходимости передавать в функцию дополнительно размер массива.

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

int nums2[] ; print(nums2); // ! Ошибка - в массиве nums2 6 элементов

Передача многомерного массива

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

Когда определяется параметр как указатель на массив, размер второй размерности (а также всех последующих размерностей) должен быть определен, так как данный размер является частью типа элемента. Пример объявления:

void print(int (*numbers)[3]);

Здесь предполагается, что передаваемый массив будет двухмерным, и все его подмассивы будут иметь по 3 элемента. Стоит обратить внимание на скобки вокруг имени параметра, которые и позволяют определить параметр как указатель на массив. И от этой ситуации стоит отличать следующую:

void print(int *numbers[3])

В данном случае параметр определен как массив указателей, а не как указатель на массив.

Рассмотрим применение указателя на массив в качестве параметра:

#include void print(const int(*)[3], const size_t); int main() < int table[][3] < , , >; // количество строк или подмассивов size_t rowsCount ; print(table, rowsCount); > void print(const int (*rows)[3], const size_t rowsCount) < // количество столбцов или элементов в каждом подмассиве size_t columnsCount ; for(size_t i<>; i < rowsCount; i++) < for (size_t j<>; j < columnsCount; j++) < std::cout std::cout >

В функции main определяется двухмерный массив - он состоит из трех подмассивов. Каждый подмассив имеет по три элемента.

В функцию print вместе с массивом передается и число строк - по сути число подмассивов. В самой функции print получаем количество элементов в каждом подмассиве и с помощью двух циклов перебираем все элементы. С помощью выражения rows[0] можно обратиться к первому подмассиву в двухмерном массиве, а с помощью выражения rows[0][0] - к первому элементу первого подмассива. И таким образом, манипулируя индексами можно перебрать весь двухмерный массив.

В итоге мы получим следующий консольный вывод:

1 2 3 4 5 6 7 8 9

Также мы могли бы использовать нотацию массивов при объявлении и определении функции print, которая может показаться проще, нежели нотация указателей. Но в этом случае опять же надо было бы указать явным образом вторую размерность:

#include void print(const int[][3], const size_t); int main() < int table[][3] < , , >; // количество строк или подмассивов size_t rowsCount ; print(table, rowsCount); > void print(const int rows[][3], const size_t rowsCount) < // количество столбцов или элементов в каждом подмассиве size_t columnsCount ; for( size_t i<>; i < rowsCount; i++) < for (size_t j<>; j < columnsCount; j++) < std::cout std::cout >

Как передать в функцию двумерный массив.

В одной из статей, написанной несколько лет назад, описывал для чего в си используются указатели и как с ними работать. Сегодня перечитывая, ту статью понял, что есть еще один интересный вопрос, который стоило бы рассмотреть. "Как передать в функцию двумерный массив ?"

Ответ напрашивается сам собой, использовать для этого указатель. Но просто передать адрес первого элемента двумерного массива недостаточно(по сути указатель), давайте разберемся почему.

Несмотря на то, что двумерный массив, по сути представляет собой таблицу(массив элементами которого являются массивы), в памяти все его элементы хранятся последовательно и для того, чтобы в этой последовательности как-то ориентироваться необходимо знать размер его второй мерности. То есть если у нас есть массив 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

Подскажите, пожалуйста, можно ли передать двумерный массив в функцию без использования указателей? Мне просто интересно. Если да, то как? С одномерным массивом это проходит. И изменения вносятся.

#include using namespace std; void fillArray(int Arr[], int size) < for (int i = 0; i < size; i++) < Arr[i] = i + 1; >> void showArr(int Arr[], int size) < for (int i = 0; i < size; i++) < cout > //================================== int main()
marenko.lilia
Посмотреть профиль
Найти ещё сообщения от marenko.lilia

Регистрация: 31.05.2010
Сообщений: 13,964

А чем не нравятся указатели? Лень две звёздочки поставить?
Пишем void function(int **A)<> и радуемся.

Пиши пьяным, редактируй трезвым.
Справочник по алгоритмам С++ Builder

Smitt&Wesson
Посмотреть профиль
Найти ещё сообщения от Smitt&Wesson

Пользователь
Регистрация: 25.12.2013
Сообщений: 91
Сообщение от Smitt&Wesson

А чем не нравятся указатели? Лень две звёздочки поставить?
Пишем void function(int **A)<> и радуемся.

Всё нравится )) И указатели, и две звездочки.
Но интересно человеку! Понимаете??

И почему надо использовать указатели в этом случае, если возможно и без них мы можем обойтись?

marenko.lilia
Посмотреть профиль
Найти ещё сообщения от marenko.lilia

Регистрация: 22.05.2007
Сообщений: 9,507
В С++ нет понятия двумерного массива, соответственно нет никакого специального для них механизма.
Пользователь
Регистрация: 25.12.2013
Сообщений: 91
Оказывается можно!
Немного поэкспериментировала - то получатся так:

#include using namespace std; void showArr(int Arr[][10], int size) < for (int i = 0; i < size; i++) < for (int j = 0; j < size; j++) cout > void fillArray(int Arr[][10], int size) < for (int i = 0; i < size; i++) < for (int j = 0; j < size; j++) Arr[i][j] = i; >> //================================== int main()

Главное при определении функции указать количество столбцов.
Тоже мне "профессионалы" Лишь бы поумничать.

marenko.lilia
Посмотреть профиль
Найти ещё сообщения от marenko.lilia

Регистрация: 31.05.2010
Сообщений: 13,964
Сообщение от marenko.lilia
Оказывается можно!
Тоже мне "профессионалы" Лишь бы поумничать.

У каждого свой стиль. Я статическими массивами не пользуюсь, а динамические в функцию передаются по указателям.

Пиши пьяным, редактируй трезвым.
Справочник по алгоритмам С++ Builder

Smitt&Wesson
Посмотреть профиль
Найти ещё сообщения от Smitt&Wesson

Пользователь
Регистрация: 25.12.2013
Сообщений: 91

Согласна.
Мне просто интересно было разобраться можно ли так сделать, как спрашивала.

Если вас задело - не обижайтесь ) Это шутка была! По Вам то видно, что Вы дядя серьезный ))

marenko.lilia
Посмотреть профиль
Найти ещё сообщения от marenko.lilia

Регистрация: 31.05.2010
Сообщений: 13,964
Сообщение от marenko.lilia

Согласна.
Мне просто интересно было разобраться можно ли так сделать, как спрашивала.

Если вас задело - не обижайтесь ) Это шутка была! По Вам то видно, что Вы дядя серьезный ))

Я ещё и весёлый. Шутки понимаю .
Пиши пьяным, редактируй трезвым.
Справочник по алгоритмам С++ Builder

Smitt&Wesson
Посмотреть профиль
Найти ещё сообщения от Smitt&Wesson

Регистрация: 16.12.2011
Сообщений: 2,329
Сообщение от marenko.lilia
Подскажите, пожалуйста, можно ли передать двумерный массив в функцию без использования указателей?

#include using namespace std; template void fillArray(int (&Arr)[N]) < for (int i = 0; i < N; i++) Arr[i] = i + 1; >template void showArr(const int (&Arr)[N]) < for (int i = 0; i < N; i++) cout //================================== int main()

Обратите внимание: размер сишного массива известен времени компиляции, поэтому передавать его размер в качестве аргумента функции не нужно.

Компилятор вычислит размер массива автоматически.

Сообщение от Smitt&Wesson

У каждого свой стиль. Я статическими массивами не пользуюсь, а динамические в функцию передаются по указателям.

На языке с++ не существует динамических массивов.
Последний раз редактировалось Stilet; 02.09.2014 в 19:35 .
Регистрация: 16.12.2011
Сообщений: 2,329
Сообщение от marenko.lilia
Оказывается можно!

void showArr(int Arr[][10], int size)

Вы ошиблись: в данном случае вы передали указатель.
Пусть вас не смущает отсутствие звездочки - это наследие языка си.

На языке си для массивов существует альтернативный синтаксис для аргументов функций являющихся массивами.

Вообще, у вас есть три способа передать данные в функцию:
1. По значению. В функцию передается копия аргумента.
2. По указателю. В функцию передается указатель, который инициализирован адресом аргумента.
3. По ссылке. В функцию передается ссылка аргумента.

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

На языке си нет ссылок, только указатели.

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

#include #include using namespace std; void showArr(int Arr[][10], int size) < cout::value int main()

Резюмируя: если хотите передать массив в функцию не через указатель, то передавайте по ссылке.

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

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