Насколько я понимаю, в функциях на C стек обычно используется для хранения параметров, передаваемых функции, а также для локальных переменных функции. Я знаю, что это зависит от компилятора и платформы, поскольку также можно использовать регистры, но допустим, что в этом случае просто используется стек.
Резервируется ли обычно место в стеке для локальных переменных, независимо от того, где они определены внутри этой функции?
Например, если в функции есть условие if, и когда оно истинно, переменные определяются внутри блока if. Будут ли операции push() вызываться только при входе в блок, а операции pop() — при выходе из блока?
Или это тот случай, когда место в стеке резервируется для этих переменных независимо от того, истинно ли условие if или нет?
@WeatherVane: Извините, я удалил свой комментарий до того, как вы на него ответили, потому что он был частично неточным. Чтобы ответить на ваш вопрос: в вашем примере без активной оптимизации компилятора оба цикла не будут использовать одни и те же местоположения стека для счетчика циклов. Вотдемонстрация. Это относится как к gcc, так и к clang. Если я активирую оптимизацию компилятора, счетчики циклов сохраняются в регистре ЦП, а не в стеке. Обновлено: О, кажется, вы также удалили свой комментарий, пока я на него отвечал. :-)
@AndreasWenzel это зависит от компилятора. В стандарте C даже не упоминается какой-либо стек, не говоря уже о том, как его следует использовать.
«Будут ли операции push() вызываться только при входе в блок, а операции pop() — при выходе из блока?» --> Обычно нет. Это зависит от компилятора. «Или это тот случай, когда место в стеке резервируется для этих переменных независимо от того, истинно ли условие if или нет?» --> Обычно. Это зависит от компилятора. @ Engineer999, почему это различие важно?
Кажется, есть 2 вопроса; а) все ли пространство стека предварительно выделено в начале функции или выгружается/выталкивается по требованию? и б) будет ли компилятор расточительно использовать пространство стека, если определены (или не используются) переменные, которые не имеют одной и той же области видимости?





Ну, это полностью зависит от реализации. Давайте проигнорируем все, что касается оптимизации, и объясним этот вопрос по стандарту C.
Во-первых, стандарт C ничего не указывает на структуру памяти. Таким образом, реализации (т. е. каким-то образом компиляторы) могут выбирать любой способ выделения пространства памяти для объектов (т. е. каким-то образом переменных), если они подчиняются ограничению времени жизни.
Время жизни объекта — это часть выполнения программы, в течение которой для него гарантированно зарезервировано пространство.
Объекты, определенные в операторе if (без спецификаторов static и thread_local), имеют «автоматическую продолжительность хранения», время жизни которой начинается с момента входа в блок и заканчивается при выходе из блока.
Таким образом, ответ на вопрос «выделяется ли пространство памяти для объекта автоматической продолжительности хранения заранее или вовремя» полностью зависит от реализации.
На практике «локальные переменные» часто выделяются заранее (даже в древних x86 ISA, таких как 8086). А вот для VLA их можно выделить только вовремя. Если вы действительно хотите узнать поведение конкретной реализации, просто обратитесь к ее документации (например, руководству пользователя GCC и внутреннему документу).
Это зависит от компилятора [оптимизатора]. Он может делать и то, и другое, по своему выбору в зависимости от компилируемого кода. Для переменных области действия функции, если им требуется пространство кадра стека, это обычно делается в прологе/эпилоге функции. Но переменные с областью действия блока можно перемещать/извлекать динамически, особенно для VLA:
void func(int size) { for (int loop = 1; loop <= 10; ++loop) { int array[size + loop]; do_stuff(array,size,loop); } }