При передаче указателя или массива в функцию в языке C фактически передается копия значения указателя (то есть адрес памяти), а не сам массив или содержимое памяти. Исторически массивы в C не передаются по значению — вместо этого в функцию уходит указатель на первый элемент массива. Этот механизм экономит память, но чреват нежелательными побочными эффектами при неверном использовании.
Проблема — путаница между указателями и массивами: часто разработчики считают, что внутри функции по массиву нельзя менять внешний массив или что функция знает размер переданного массива автоматически. На практике функция теряет исходный размер массива и может легко выйти за его пределы.
Решение — всегда явно передавать размер массива как отдельный аргумент, чётко понимать разницу между копией указателя и копией объекта, не забывать, что любые изменения по указателю отражаются на исходных данных.
Пример корректной передачи массива:
void print_array(const int* arr, size_t size) { for (size_t i = 0; i < size; ++i) printf("%d ", arr[i]); } int main() { int nums[] = {1,2,3,4,5}; print_array(nums, sizeof(nums)/sizeof(nums[0])); return 0; }
Ключевые особенности:
Может ли функция узнать длину переданного массива, если он был объявлен как int arr[10]?
Ответ: Нет, внутри функции выражение sizeof(arr) вернёт размер указателя, а не всего массива. Размер нужно передавать отдельно.
Передача массива как int arr[] и как int arr в функции — это одно и то же?*
Ответ: Да, в сигнатуре функции это эквивалентно — в обоих случаях передаётся указатель на int. Различия есть только в синтаксисе.
Изменяя элементы массива внутри функции, изменится ли исходный массив?
Ответ: Да, поскольку передан указатель, функция изменяет память, на которую он указывает.
Проект реализовал функцию инициализации массивов, определяя размер внутри функции через sizeof(arr) / sizeof(arr[0]). На этапе тестирования функция работала, но при обработке других массивов — затирала чужую память или работала некорректно.
Плюсы:
Минусы:
Функция всегда принимала размер массива отдельным параметром, длина вычислялась вызвавшей стороной. Внутри функции работали только с переданными параметрами.
Плюсы:
Минусы: