Чтобы понять, почему массивы переменного размера сложнее реализовать, вам нужно немного узнать о том, как обычно применяются переменные продолжительности автоматического хранения («локальные»).
Локальные переменные, как правило, хранятся в стеке времени выполнения. Стек в основном представляет собой большой массив памяти, который последовательно выделяется локальным переменным и с единственным индексом, указывающим на текущую "отметку максимальной воды". Этот индекс является указателем стека .
Когда функция введена, указатель стека перемещается в одном направлении, чтобы выделить память в стеке для локальных переменных; при выходе из функции указатель стека перемещается назад в другом направлении, чтобы освободить их.
Это означает, что фактическое расположение локальных переменных в памяти определяется только со ссылкой на значение указателя стека при вводе функции 1 . Код в функции должен обращаться к локальным переменным через смещение от указателя стека. Точные смещения, которые будут использоваться, зависят от размера локальных переменных.
Теперь, когда все локальные переменные имеют размер, который фиксируется во время компиляции, эти смещения от указателя стека также фиксируются - поэтому они могут быть закодированы непосредственно в инструкции, которые генерирует компилятор. Например, в этой функции:
void foo(void)
{
int a;
char b[10];
int c;
a
может быть получен как STACK_POINTER + 0
, b
может быть получен как STACK_POINTER + 4
, а c
может быть получено как STACK_POINTER + 14
.
Однако, когда вы вводите массив переменного размера, эти смещения больше не могут быть вычислены во время компиляции; некоторые из них будут различаться в зависимости от размера массива при вызове функции. Это значительно усложняет процесс написания компиляторов, потому что теперь они должны писать код, который обращается к STACK_POINTER + N
- и поскольку сам N
меняется, его также нужно где-то хранить. Часто это означает два доступа: один к STACK_POINTER + <constant>
для загрузки N
, затем другой для загрузки или сохранения актуальной локальной переменной, представляющей интерес.
1. Фактически, «значение указателя стека при входе в функцию» является настолько полезным значением, что оно имеет собственное имя - указатель кадра - и многие ЦП предоставляют отдельный регистр, выделенный для хранения указателя кадра. На практике это обычно указатель кадра, из которого вычисляется расположение локальных переменных, а не сам указатель стека.