Как передать массив в функцию си
Перейти к содержимому

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

  • автор:

Передача массива в функцию и возврат из функции

Особенность передачи массивов в функции в языке Си в том, что передается не сам массив, а адрес массива, который хранится в локальном указателе на него.

Это можно сделать по-разному, но результат будет одинаковый:

  • void some_function(int array[]);
  • void some_function(int *array);

При этом обязательно нужно указать тип элемента массива.

Размер массива в функцию автоматически не передается, поэтому если размер массива заранее (на этапе компиляции) не оговорен, то нужно передать параметр, который содержит количество элементов в массиве, например number_of_elements:

void some_function(int array[], int number_of_elements);

Следующая программа передает массивы в функцию show_array, которая использует цикл for для вывода значений массивов:

show_array.c

void show_array (int array [], int number_of_elements)
for ( int i = 0; i < number_of_elements; i++) printf("%d\t", array[i]);
>
printf(«\n»);
>

int main()
int little_numbers[5] = ;
int big_numbers[3] = ;
show_array(little_numbers, 5);
show_array(big_numbers, 3);
>

Массив просто передается в функцию по имени (а его имя — это адрес первого элемента), а также указывает параметр, который сообщает функции количество элементов, содержащихся в массиве:

Изменение массива из функции

Возможно ли поменять значения элементов из функции?

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

Следующая программа использует функцию get_values, чтобы присвоить три значения массиву numbers:

values_from_keyboard.c

#include
void read_array(int array[], int number_of_elements)
for(int i = 0; i < number_of_elements; i++)
printf(«Введите значение №%d: «, i);
scanf(«%d», &array[i]);
>
>

int main()
int numbers[3] = ;
read_array (numbers, 3); //массив будет изменен!
printf(» Значения массива\n»);
for (int i = 0; i < 3; i++) printf(" numbers [%d] \n", i);
>

Как видите, программа передает массив в функцию по имени, а функция присваивает массиву элементы.

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

Массивы и функции в языке Си. Передача указателя на массив

Массивы, также как остальные переменные, можно передавать в функции в качестве аргументов. Рассмотрим такую программу:

#include #include #include #define N 10 void rand_fill(int arr[], int min, int max); int main() { int numbers[N]; rand_fill(numbers, 30, 90); for (int i = 0; i  N; i++) printf("%d ", numbers[i]); printf("\n"); } void rand_fill(int arr[], int min, int max) { srand(time(NULL)); for (int i = 0; i  N; i++) arr[i] = rand() % (max - min + 1) + min; }

В теле функции main объявляется массив, состоящий из 10 элементов. Далее вызывается функция rand_fill() , которой передаются в качестве аргументов имя массива и два целых числа.

Если посмотреть на функцию rand_fill , то можно заметить, что ее первый параметр выглядит немного странно. Функция принимает массив неизвестно какого размера. Если предположить, что массивы передаются по значению, т. е. передаются их копии, то как при компиляции будет вычислен необходимый объем памяти для функции rand_fill , если неизвестно какого размера будет один из ее параметров?

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

Описание вида arr[] в параметрах функций говорит о том, что в качестве значения мы получаем указатель на массив, а не обычную (скалярную) переменную типа int , char , float и т.п.

Если в функцию передается только адрес массива, то в теле функции никакого массива не существует, и когда там выполняется выражение типа arr[i] , то на самом деле arr ‒ это не имя массива, а переменная-указатель, к которой прибавляется смещение. Поэтому цикл в функции rand_fill можно переписать на такой:

for (int i = 0; i  N; i++) *arr++ = rand() % (max - min + 1) + min;

В теле цикла результат выражения справа от знака присваивания записывается по адресу, на который указывает arr . За это отвечает выражение *arr . Затем указатель arr начинает указывать на следующую ячейку памяти, т.к. к нему прибавляется единица ( arr++ ). Еще раз: сначала выполняется выражение записи значения по адресу, который содержится в arr ; после чего изменяется адрес, содержащийся в указателе (сдвигается на одну ячейку памяти определенного размера).

Поскольку мы можем изменять arr , это доказывает, что arr — обычный указатель, а не имя массива. Тогда зачем в заголовке функции такой гламур, как arr[] ? Действительно, чаще используют просто переменную-указатель:

void rand_fill(int *arr, int min, int max);

Хотя в таком случае становится не очевидно, что принимает функция ‒ указатель на обычную переменную или все-таки на массив. В любом случае она будет работать.

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

void rand_fill(int *arr, int n, int min, int max) { srand(time(NULL)); for (int i = 0; i  n; i++) *arr++ = rand() % (max - min + 1) + min; }

В данном случае параметр n — это количество обрабатываемых элементов массива.

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

int arr_sum(int *arr) { int s = 0, i; for(i = 0; i  N; i++) { s = s + arr[i]; } return s; }

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

int arr_sum(const int *arr);

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

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

#include #include #include #define N 10 void rand_fill(int *arr, int min, int max); void arr_inc_dec(int arr[], char sign); void arr_print(int *arr); int main() { int numbers[N], i, minimum, maximum; char ch; printf("Enter minimum & maximum: "); scanf("%d %d", &minimum, &maximum); rand_fill(numbers, minimum, maximum); arr_print(numbers); scanf("%*c"); // избавляемся от \n printf("Enter sign (+, -): "); scanf("%c", &ch); arr_inc_dec(numbers, ch); arr_print(numbers); } void rand_fill(int *arr, int min, int max) { srand(time(NULL)); for (int i = 0; i  N; i++) *arr++ = rand() % (max - min + 1) + min; } void arr_inc_dec(int *arr, char sign) { for (int i = 0; i  N; i++) { if (sign == '+') arr[i]++; else if (sign == '-') arr[i]--; } } void arr_print(int *arr) { printf("The array is: "); for (int i = 0; i  N; i++) printf("%d ", *arr++); printf("\n"); }

Теперь у пользователя запрашивается минимум и максимум, затем создается массив из элементов, значения которых лежат в указанном диапазоне. Массив выводится на экран с помощью функции arr_print() . Далее у пользователя запрашивается знак + или -. Вызывается функция arr_inc_dec() , которая в зависимости от введенного знака увеличивает или уменьшает на единицу значения элементов массива.

В функциях rand_fill и arr_print используется нотация указателей. Причем в теле функций значения указателей меняются: они указывают сначала на первый элемент массива, затем на второй и т.д. В функции arr_inc_dec используется вид обращения к элементам массива. При этом значение указателя не меняется: к arr прибавляется смещение, которое увеличивается на каждой итерации цикла. Ведь на самом деле запись arr[i] означает *(arr+i) .

При использовании нотации обращения к элементам массива программы получаются более ясные, а при использовании записи с помощью указателей они компилируются чуть быстрее. Это связано с тем, что когда компилятор встречает выражение типа arr[i] , он тратит время на преобразование его к виду *(arr+i) .

Напишите программу, в которой из функции main в другую функцию передаются два массива: «заполненный» и «пустой». В теле этой функции элементам «пустого» массива должны присваиваться значения, так или иначе преобразованные из значений элементов «заполненного» массива, который не должен изменяться.

Курс с решением задач:
pdf-версия

Передача массива в функцию, подсчет длины массива по указателю

    В С++ массивы можно инициализировать следующим образом:

int arr[] = ; // длина массива определяется после инициализации

Как следствие, его можно передать в функцию таким же способом:

void func(int arr[])< //your code >
void func(int* arr) < //your code >int arr[5] = ;

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

int main()< int arr[5] = ; cout 
void func(int* arr, int length)< //your code >

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

int len(int* arr)

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

Перенос массива из одной функции в другую в Си

Есть две функции. Надо реализовать передачу массива из одной функции в другую. Сам я пробовал реализовать, но без понятия как это сделать.

#include #include #include #include int local(int*mass, int g, int size) < while (1) < printf("%d", mass[g]); int* massiv; massiv = (int*)malloc(sizeof(int) * size); int k = 0; while (k != size) < printf("%d", mass[k]); //пытаюсь передать все значения в другой массив k++; >printf("O"); //проверяю как передался массив int loc = 0; for (int i = 0; i < size; i++) < if (mass[i] >mass[i - 1] && mass[i] > mass[i + 1]) < loc++; //считает локальные максимумы >> printf("%d", loc); printf("\n"); break; > > int mass() //Создает массив < int* mass; int size; printf("Введите размер массива: "); scanf_s("%d", &size); mass = (int*)malloc(sizeof(int) * size); printf("Введите массив: "); for (int i = 0; i < size; i++) < scanf_s("%d", &mass[i]); >printf("\n"); for (int g = 0; g < size; g++) < printf("%d ", mass[g]); >printf("\n"); for (int i = 0; i < size; i++) < local(mass, i, size); //передает массив в другую функцию >> 
Введите размер массива: 3 Введите массив: 3 4 5 3 4 5 3345O1 4345O1 5345O1 

введите сюда описание изображения

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

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

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