Передача в функцию двумерного массива
Почти все рассуждения, которые относятся к передаче одномерного массива в функцию, остаются справедливыми и для двумерных массивов. Исключение составляет тип данных формального параметра, соответствующего массиву.
Замечание
Для двумерных массивов (т.е. матриц) важнейшей характеристикой является количество элементов в строке (или столбцов матрицы). Действительно, 20 чисел можно представить в виде двумерного массива многими способами: 20*1, 2*10, 4*5, 10*2 и т.д. Так как элементы массивов перебираются по строкам (например, при инициализации), то задание количества элементов в строке однозначно определит структуру массива.
В Си имя массива — это указатель на тип элемента массива. Двумерный массив — это одномерный массив строк матрицы (тоже одномерных массивов). Поэтому имя двумерного массива — это указатель на строку матрицы, т.е. на массив из конкретного числа элементов.
Пример
В функцию f нужно передать единственный аргумент — двумерный массив arr2 чисел типа int. Размеры массива: 6 строк и 8 столбцов.
Тогда прототип функции должен будет выглядеть следующим образом (с точностью до имени формального параметра):
void f(int (*a)[8]); (2)
Замечания
1. Если при передаче одномерного массива конкретные размеры массива указывать было не нужно, то для двумерного массива обязательно должно быть указано количество столбцов (второй размер, в примере это 8).
Конструкция (*a)[8] читается, как "указатель на массив из 8 элементов" (запись *a[8] означает "массив из 8 указателей", что не соответствует условию примера).
2. Двумерный массив — это одномерный массив строк матрицы. Поэтому в функции информация о количестве его элементов (строк переданного ей двумерного массива) теряется.
Для описания аргументов, принимающих двумерные массивы, также имеется вторая синтаксическая форма:
void f(int a[][8]);
Такая форма описания аргумента более проста и понятна. Но вновь это опять только внешнее представление, потому что компилятор перед трансляцией программы преобразует его к виду (2).
Если указать первый размер, то ошибки компиляции не будет, но этот размер никак использоваться не будет.
ЗАДАНИЕ 3 (передача в функцию двумерного массива)
Написать функцию total2, которая вычисляет сумму элементов любого двумерного массива целых чисел с тремя элементами в строке. Функция возвращает подсчитанную сумму.
1. Функция main.
1.1. В функции main определен двумерный числовой массив arr2[][3] со значениями типа int. Массив инициализирован так, чтобы в нем было 4 полных строки (т.е. размеры 4*3).
1.2. С помощью sizeof определяется размер объекта arr2. Используя этот размер и известное количество столбцов (их 3), подсчитать количество строк в массиве. Вывести на экран оба результата.
1.3. Выполнить вызов функции total2, передав ей
а) массив arr2,
б) количество строк в массиве.
2. Функция total2.
В функции total2 выполняются следующие действия.
2.1. С помощью sizeof определяется размер объекта, соответствующего формальному параметру-массиву, и этот размер выводится на экран.
Сравнить эту величину с той, что была получена в первом пункте задания, и объяснить результаты.
2.2. С помощью вложенных циклов подсчитывается сумма элементов двумерного массива, которая возвращается затем в main. Необходимое для одного из операторов цикла количество элементов в строке массива указать числом (т.е. 3). В следующем задании будет разработан более универсальная программа.
Замечание
Хотя количество элементов в строке через аргумент не передается, его можно вычислить следующим образом. Пусть a2 обозначает формальный параметр, через который в функцию передается массив. По своему смыслу — это указатель на строку массива (т.е. на одномерный массив). Если к a2 применить операцию разадресации, то мы получим сам массив.
Теперь количество элементов в строке можно найти, если объем памяти, занимаемый строкой, поделить на размер одного элемента (sizeof(*a2)/sizeof(int)).
2.3 Проверить работу программы.
ЗАДАНИЕ 4 (универсальный вариант программы)
Разрабатывается другой вариант программы для задачи предыдущего задания. Для преобразований программы, сохранить файл задания 3 под другим именем.
1. Чтобы сделать функцию total2 более универсальной, критический для массива размер (число колонок) везде, где он встречается (в определении массива arr2, в определениях функции и прототипа, граничное значение в операторе цикла), задать с помощью именованной константы COLUMNS.
Определение константы COLUMNS выполнить в начале файла с помощью директивы
#define COLUMNS 3
Проверить работу программы.
Замечание
Использование именованной константы COLUMNS не только делает функцию total2 применимой для массивов с любой длиной строки, но и избавляет от необходимости вычислять в функции количество элементов в строке массива (см. предыдущий пункт).
Именованная константа, задающая этот размер, доступна в любой части программы, в том числе и в функции total2.
4. Чтобы убедиться, что внутри функции total2 обрабатываются непосредственно элементы массива arr2, добавить в total2 (перед оператором возврата) обнуления первой строки массива.
Соответственно, в функции main добавить после оператора вывода на экран подсчитанной суммы печать элементов первой строки массива arr2.
Изменить значение COLUMNS на 4, затем на 6. Убедиться, что сумма подсчитывается правильно, а количество выведенных обнуленных элементов меняется соответственно размеру.