Здесь короткая программа на языке C, которая запрашивает у пользователя число, создает массив переменных длины этого размера и затем использует арифметику указателя для перехода по выделенным элементам:
#include <stdio.h>
int main() {
/* Read a size from the user; inhibits compiler optimizations. */
int n;
scanf("%d", &n); // Yes, I should error-check. :-)
/* We now have a VLA. */
int arr[n];
/* What is the type of &arr? */
void* ptr = (&arr) + 1;
/* Seems like this skipped over things properly... */
printf("%p\n", arr);
printf("%p\n", ptr);
}
Вы можете попробовать на ideone, если хотите. Вывод предполагает, что строка
void* ptr = (&arr) + 1;
принимает адрес arr
и, с точки зрения размера, выполняет шаги по всем элементам n
в массиве переменной длины.
Если бы это не был массив переменной длины, мне было бы совершенно удобно, как это работает. Компилятор будет знать тип arr
(он будет int (*) [K]
для некоторой константы K
), поэтому, когда мы добавим его в &arr
, он может пропустить правильное количество байтов.
Это ясно, как во время выполнения мы могли бы оценить (&arr) + 1
. Компилятор фиксирует размер arr
где-то в стеке, и когда мы добавляем его в (&arr)
, он знает, чтобы загрузить этот размер, чтобы вычислить, сколько байтов пропустить.
Однако я не знаю, что говорит язык типа выражения &arr
. Назначен ли какой-то статический тип, который указывает на массив переменной длины (что-то вроде int (*) [??]
)? Говорит ли спецификация "тип выражения int (*) [K]
, где K
- какой размер назначается массиву во время выполнения?" Не разрешает ли спецификация обращение к адресу массива переменной длины, и компилятор просто разрешает его?