Чтобы понять поведение компилятора, вы должны учитывать, что в языке C каждая переменная имеет класс хранения ( ISO / IEC 9899: 201x §6.2.4 Длительность хранения объектов )которые характеризуют его поведение и его « жизнь », что означает существование такого объекта (переменная является объектом) и законные условия доступа к нему.Классы хранения 4: статические, потоковые, автоматические и распределенные.Последние используют динамическое распределение памяти.
В вашем случае массив arr[2048]
является автоматическим объектом, время жизни которого определяется (в том же абзаце стандарта @ point 6) как:
Для такого объекта, у которого нет типа массива переменной длины, его время жизни простирается от входа в блок, с которым он связан, до тех пор, пока выполнение этого блока не закончится каким-либо образом.(Ввод закрытого блока или вызов функции приостанавливает, но не прекращает выполнение текущего блока.)
Если блок вводится рекурсивно, каждый раз создается новый экземпляр объекта.
Начальное значение объекта не определено .
Если для объекта указана инициализация, она выполняется каждый раз, когда объявление или составной литерал достигается висполнение блока ;в противном случае значение становится неопределенным при каждом достижении декларации.
Это объясняет, что:
- Жизнь объекта начинается с начала блока, в котором он находитсяопределены.
- Начальное значение (в нашем случае содержимое массива) неопределенно: компилятор не инициализирует область памяти.И когда указана инициализация, она выполняется, когда выполнение достигает блока .
Первый пункт ясен и уже является ответом на ваш вопрос.Код, на который вы ссылаетесь:
{ //Block init
int arr[2048] = {0};
//Doing something related to arr;
} // block end
Если вы не введете в блок life вашего объекта, массив не начинается: массив не существует.Конечно, при этом условии никакие операции не могут быть выполнены над объектом, даже инициализация.
Теперь точка 2 помогает лучше уточнить.Выражение:
int arr[2048] = {0};
Функционально не интерпретируется компилятором как объявление с инициализацией объекта из-за класса хранения объекта массива.Кроме того, оно, по существу, рассматривается как объявление плюс присвоение .
В чем разница?
Реализовано объявление инициализированной переменной, имеющей класс хранения, отличный от автоматическогос механизмом, прозрачным для кода пользователя, статически присваивающим значения в разделе BSS, или с кодом, принадлежащим прологам и эпилогам компилятора, что может произойти, даже если к объекту нет доступа .
В другом случае код инициализации, присвоение является частью кода пользователя и по этой причине выполняется в соответствии с логикой потока выполнения .
Это официальное поведение.Изучив скрытно, вы можете увидеть, что в некоторых случаях пространство для автоматических переменных выделяется заранее с начала жизни объекта, но это поведение строго зависит от архитектуры ЦП, и в основном, когда это происходит, не создают функционального расхождения междукод языкового стандарта (который является базовым свойством совместимого компилятора ).