ПрограммированиеC разработчик

Чем отличаются указатели и массивы в языке C? Как правильно передавать массив в функцию?

Проходите собеседования с ИИ помощником Hintsage

Ответ.

Указатели и массивы в C связаны, но это не одно и то же:

  • Массив — совокупность однотипных элементов в памяти, определяемый размером.
  • Указатель — переменная, хранящая адрес в памяти, куда может указывать массив или отдельный объект.

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

Синтаксис передачи:

void foo(int arr[], int size) { // arr — фактически int* for (int i = 0; i < size; ++i) printf("%d ", arr[i]); } int main() { int data[5] = {1,2,3,4,5}; foo(data, 5); }

Вопрос с подвохом.

Вопрос: Что вернет выражение sizeof(arr) внутри функции, если arr — это параметр типа int arr[]?

Ответ: Возвращает размер указателя (sizeof(int*)), а не размер всего массива. Потому что в функцию передается указатель на первый элемент, информация о длине теряется.

Пример кода:

void printSize(int arr[]) { printf("%zu ", sizeof(arr)); // sizeof(int*) обычно 4 или 8 }

История

В коммерческом проекте для вычисления среднего значения в массиве был написан код, где для количества элементов внутри функции брали sizeof(arr) / sizeof(arr[0]), что возвращало всегда 1 или 2 вместо реального количества элементов. Из-за этого программа некорректно работала с данными, некорректно усредняла значения.


История

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


История

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