Определение переменной внутри условия if и программа не входит

Насколько я понимаю, в функциях на C стек обычно используется для хранения параметров, передаваемых функции, а также для локальных переменных функции. Я знаю, что это зависит от компилятора и платформы, поскольку также можно использовать регистры, но допустим, что в этом случае просто используется стек.

Резервируется ли обычно место в стеке для локальных переменных, независимо от того, где они определены внутри этой функции?

Например, если в функции есть условие if, и когда оно истинно, переменные определяются внутри блока if. Будут ли операции push() вызываться только при входе в блок, а операции pop() — при выходе из блока?

Или это тот случай, когда место в стеке резервируется для этих переменных независимо от того, истинно ли условие if или нет?

Это зависит от компилятора [оптимизатора]. Он может делать и то, и другое, по своему выбору в зависимости от компилируемого кода. Для переменных области действия функции, если им требуется пространство кадра стека, это обычно делается в прологе/эпилоге функции. Но переменные с областью действия блока можно перемещать/извлекать динамически, особенно для VLA: void func(int size) { for (int loop = 1; loop <= 10; ++loop) { int array[size + loop]; do_stuff(array,size,loop); } }

Craig Estey 26.05.2024 22:18

@WeatherVane: Извините, я удалил свой комментарий до того, как вы на него ответили, потому что он был частично неточным. Чтобы ответить на ваш вопрос: в вашем примере без активной оптимизации компилятора оба цикла не будут использовать одни и те же местоположения стека для счетчика циклов. Вотдемонстрация. Это относится как к gcc, так и к clang. Если я активирую оптимизацию компилятора, счетчики циклов сохраняются в регистре ЦП, а не в стеке. Обновлено: О, кажется, вы также удалили свой комментарий, пока я на него отвечал. :-)

Andreas Wenzel 26.05.2024 23:19

@AndreasWenzel это зависит от компилятора. В стандарте C даже не упоминается какой-либо стек, не говоря уже о том, как его следует использовать.

Weather Vane 27.05.2024 00:32

«Будут ли операции push() вызываться только при входе в блок, а операции pop() — при выходе из блока?» --> Обычно нет. Это зависит от компилятора. «Или это тот случай, когда место в стеке резервируется для этих переменных независимо от того, истинно ли условие if или нет?» --> Обычно. Это зависит от компилятора. @ Engineer999, почему это различие важно?

chux - Reinstate Monica 27.05.2024 00:51

Кажется, есть 2 вопроса; а) все ли пространство стека предварительно выделено в начале функции или выгружается/выталкивается по требованию? и б) будет ли компилятор расточительно использовать пространство стека, если определены (или не используются) переменные, которые не имеют одной и той же области видимости?

Weather Vane 27.05.2024 01:32
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
88
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Ну, это полностью зависит от реализации. Давайте проигнорируем все, что касается оптимизации, и объясним этот вопрос по стандарту C.

Во-первых, стандарт C ничего не указывает на структуру памяти. Таким образом, реализации (т. е. каким-то образом компиляторы) могут выбирать любой способ выделения пространства памяти для объектов (т. е. каким-то образом переменных), если они подчиняются ограничению времени жизни.

Время жизни объекта — это часть выполнения программы, в течение которой для него гарантированно зарезервировано пространство.

Объекты, определенные в операторе if (без спецификаторов static и thread_local), имеют «автоматическую продолжительность хранения», время жизни которой начинается с момента входа в блок и заканчивается при выходе из блока.

Таким образом, ответ на вопрос «выделяется ли пространство памяти для объекта автоматической продолжительности хранения заранее или вовремя» полностью зависит от реализации.

На практике «локальные переменные» часто выделяются заранее (даже в древних x86 ISA, таких как 8086). А вот для VLA их можно выделить только вовремя. Если вы действительно хотите узнать поведение конкретной реализации, просто обратитесь к ее документации (например, руководству пользователя GCC и внутреннему документу).

Другие вопросы по теме