Как массивы "знают", насколько они велики?Как это реализовано?
Массивы не не знают, насколько они велики - с массивом нет метаданных, указывающих размер (или тип, или что-либо еще). Во время перевода компилятор знает, насколько велик массив, и все, что зависит от этих знаний (арифметика указателей, sizeof
операции и т. Д.), Обрабатывается в это время.После того, как машинный код сгенерирован, массивы - это просто тупые куски памяти - невозможно определить во время выполнения , насколько велик массив, глядя на сам объект массива (за исключением изменяемых типов, таких как переменныемассивы длины, sizeof
операции вычисляются во время перевода, а не во время выполнения).
В целом, как массивы реализованы на языке Си?(Компилятор делает это, или ядро?
Массивы - не более чем непрерывная последовательность объектов одного типа. Для объявления
T arr[N]; // for any type T
вы получаете
+---+
arr: | | arr[0]
+---+
| | arr[1]
+---+
| | arr[2]
+---+
...
+---+
| | arr[N-1]
+---+
Не существует arr
объекта, независимого от самих элементов массива, а также метаданных, нигде не выделенных для размера, начального адреса, типа или чего-либо еще.
Индексоперация arr[i]
определена как *(arr + i)
- учитывая начальный адрес массива, смещение i
элементов ( не байтов! ) от этого адреса и разыменование результата.
Вы правы, что массивы не являются указателями - однако, если это не операнд операторов sizeof
или унарных &
, или строковый литерал, используемый для инициализации массива символов в объявлении, выражение типа массива будет преобразовано («распад») в выражение типа указателя, а значением выражения будет адрес первого элемента массива (опять же, tвсе это делается во время перевода, а не во время выполнения).
Таким образом, когда вы пишете что-то вроде x = arr[i];
, компилятор преобразует выражение arr
в значение указателя, поэтому операция с индексом работает.
Напротив, когда вы пишете ap = &arr;
, компилятор не конвертирует arr
в тип указателя.Результат по-прежнему совпадает с адресом первого элемента, но тип отличается - вместо T *
тип T (*)[N]
или «указатель на массив N-элементов T
».