Нюансы работы стека при вызове функций

Не ясно, о чем вопрос. О данном конкретном случае? Или об абстрактном общем случае? Для данного конкретного случая вопрос бессмыслен - тип

int

слишком примитивен для того, чтобы для его передачи использовать стек. Все передастся в регистрах. Для абстрактного общего случая вопрос тоже несколько бессмыслен, ибо с формальной точки зрения никакого "стека" нет.

Тем не менее, для общего случая, полагая, что работаем с некоторым абстрактноым типом

T

, а не

int

:

* Переменные

c

и

z

принадлежат

main

. Никаких гарантий об из относительном порядке расположения в памяти нет.

* Параметры функций формально создаются и удаляются в контексте вызывающего кода. То есть параметры

b

и

w

тоже принадлежат

main

и создаются и удаляются в контексте функции

main

. Имена этих параметров являются локальными в

foo

и видны только там, но сами соответствующие объекты "принадлежат"

main

.

В компиляторах, следующих "классической" спецификации С++, в которой параметры создаются непосредственно перед вызовом функции и удаляются сразу после ее вызова, еще можно думать о параметрах, как об обычных локальных переменных. Но вот в компиляторах, которые следуют Itanium ABI (GCC, Clang) параметры не удаляются сразу после завершения вызова функции, а продолжают жить до конца полного вызывающего выражения. В таких компиляторах будет особенно очевидно, что

b

и

w

создаются в

main

. В более сложном выражении

все три пары пары параметров должны будут жить одновременно до конца полного выражения, т.е. в контексте функции

main

будет созданы параметры

b_1, w_1, b_2, w_2, b_3, w_3

для первого, втрого и треьего вызова

foo

соответственно.

Относительный порядок конструкции параметров функций не специфицируется. Порядок деструкции не специфицируется тоже. Также, если я ничего не упустил, не гарантируется, что порядок деструкции будет соответствовать обращенному порядоку конструкции.