Ответ практически на все ваши вопросы заключается в том, что распределитель памяти конфиденциально знает, сколько памяти он выделил, но не тип вашего объекта. Фактически, он может знать только то, сколько блоков определенного фиксированного размера он выделил, а не обязательно столько же, сколько запрошенных байтов. Следовательно, он не знает, сколько элементов содержит «массив», и даже если он вообще используется как массив. Это. Вы просто запрашиваете столько байтов, сколько вам нужно, а затем используете эту память по своему усмотрению. Распределитель не обязан помогать вам в этом, что дает вам полную гибкость, чтобы делать все, что вы хотите.
Массив x
в вашем примере имеет известный тип и размер во время компиляции или может быть выводится во время выполнения. Другими словами, компилятор знает, что он должен поместить sh некоторое количество байтов в стек на основе значения размера и использовать их как массив определенного типа.
Не имеет смысла иметь VLA в глобальной области видимости, поскольку весь смысл VLA заключается в том, что она выделяется на основе размера переменной при входе в область действия блока. Глобальная область видимости вводится только один раз при инициализации вашей программы.