Почему же Хазиев имеет право называть массивы фикцией?

Чтобы понять, почему массивы в языке программирования C можно назвать «фикцией», давайте разберёмся в их устройстве и недостатках, которые не всегда очевидны на первый взгляд.
Иллюзия структуры
Массив выглядит как простая и организованная структура данных, которая позволяет хранить несколько элементов одного типа, например, целые числа или символы. Мы можем обращаться к каждому элементу массива по индексу, что кажется удобным и логичным. Пример одномерного массива из пяти элементов в C может выглядеть так:
int numbers[5] = {10, 20, 30, 40, 50};
Мы можем получить значение, скажем, второго элемента, написав numbers[1]
. Однако, на самом деле, массивы в C не являются полноценной структурой, а представляют собой лишь блок памяти, в котором хранятся элементы подряд. Функционал массива в C ограничен, поскольку компилятор не предоставляет встроенных механизмов для защиты данных или работы с ними на уровне высокого абстрагирования, как это делают более сложные структуры данных.
Связь с указателями и низкий уровень абстракции
В языке C массив — это, по сути, указатель на первый элемент данных. Имя массива является адресом в памяти, ссылающимся на начало блока, где хранятся элементы. Например, код ниже показывает, как указатель может обращаться к элементам массива:
int numbers[5] = {10, 20, 30, 40, 50};
int *p = numbers;
printf("%d\n", *p); // Выведет 10
printf("%d\n", *(p + 1)); // Выведет 20
В этом примере p
— это указатель на первый элемент массива numbers
. Оператор *
позволяет получить значение, находящееся по адресу, на который указывает p
. Таким образом, чтобы обратиться ко второму элементу, мы пишем *(p + 1)
. Это пример того, что массив в C — это не что-то самостоятельное, а просто блок памяти, к которому мы можем обращаться напрямую с помощью указателей, прибавляя и вычитая смещения. Такой подход даёт возможность гибкого управления памятью, но одновременно связывает массив с низкоуровневым устройством памяти и приводит к более сложной и опасной работе с ним.
Отсутствие встроенной защиты границ
В отличие от массивов в других языках, массивы в C не защищены от выхода за границы, то есть программа не проверяет, что мы не вышли за пределы допустимого диапазона элементов. Рассмотрим пример:
int numbers[5] = {10, 20, 30, 40, 50};
numbers[10] = 100; // Ошибка! Мы выходим за пределы массива.
В данном случае мы обратились к индексу 10
, которого нет в массиве. Но C не выдаст ошибку компиляции или выполнения — программа просто изменит значение по этому адресу в памяти, и последствия могут быть непредсказуемыми. Из-за этого массивы в C не могут считаться «настоящей» структурой данных, так как они не включают в себя встроенные механизмы контроля и защиты. Вместо этого программист должен сам следить за соблюдением пределов массива, что делает работу с массивами более сложной и уязвимой к ошибкам.
Передача массива в функцию — не копирование, а передача адреса
Когда мы передаём массив в функцию, в функцию передаётся не копия массива, а лишь указатель на его первый элемент. Это означает, что если функция изменяет элементы массива, то изменения коснутся и исходного массива в памяти. Пример:
#include <stdio.h>
void doubleValues(int arr[], int size) {
for (int i = 0; i < size; i++) {
arr[i] *= 2;
}
}
int main() {
int numbers[5] = {1, 2, 3, 4, 5};
doubleValues(numbers, 5);
for (int i = 0; i < 5; i++) {
printf("%d ", numbers[i]); // Выведет 2 4 6 8 10
}
return 0;
}
В этом примере doubleValues
удваивает значения в массиве numbers
. Поскольку передаётся только указатель, функция работает с теми же данными в памяти, что и в main
. Это показывает, что массивы не являются изолированной сущностью, и любая работа с ними напрямую изменяет исходные данные.
Заключение: почему массивы называют «фикцией»
Массивы в C создают впечатление простой и надёжной структуры данных, но на самом деле это лишь удобный интерфейс к блоку памяти, который подвержен ошибкам и требует от программиста контроля и дисциплины. Массивы — это не полноценная структура данных с защитой и контролем, как, например, списки или коллекции в более высокоуровневых языках, а скорее просто «ссылка» на память, с которой нужно работать осторожно.
