Вы можете запускать свою программу шаг за шагом в голове (или в отладчике) и можете считать все активные переменные в каждом кадре call stack (затем получить максимальную сумму из них).
В вашем конкретном примере, не предполагая оптимизации, самый глубокий стек вызовов происходит в return c;
заявления в g
наречен f
наречено main
. Таким образом, у нас есть 3 стек вызовов кадров с 3 переменными для g
(a
, b
, c
;! Я предполагаю, что формали, как локальные переменные, это не всегда верно на практике), 2 переменных для f
(a
, b
), и 3 переменные для main
.
Ваш учитель, вероятно, ожидает, что вы нарисуете стек вызовов в его самом глубоком состоянии. Я оставляю это вам.
На практике несколько переменных не занимают пространства стека, например. потому что они сидят в регистре или разделяют слот стека с другими переменными. Это компилятор и ABI, а также архитектура процессора и операционная система.
Однако, как Ilya answered, хороший компилятор преобразит вашу программу для optimization purposes, так что на практике ответ может быть другим.
При использовании GCC, вы можете попытаться посмотреть на сгенерированный код на ассемблере (с использованием gcc -fverbose-asm -S
), и вы увидите, что результат и количество используемых переменных зависит от флагов оптимизации (т.е. -O1
, -O2
, и т.д .. или их отсутствие). Вы также можете использовать флаг -fstack-usage GCC. Вы даже можете попробовать флаг -fdump-tree-all
в gcc
, который дает сотни файлов дампов, подробно объясняющих различные промежуточные представления (Gimple, SSA, ...) вашей программы внутри компилятора.
Читайте также wikipages на continuations (также, возможно, call/cc), tail call, recursion и inline expansion.
BTW, наличие стека вызовов не является строго обусловленным стандартом C99 (но я не знаю, как реализация C не использует стеки вызовов). Если вам интересно, вы должны прочитать старую статью A.Appel garbage collection can be faster than stack allocation (в которой объясняется реализация SML, не использующая какой-либо стек вызовов, поскольку он выделяет каждый кадр «call frame», a.k.a. «frame продолжения», в кучу мусора).
Я также предлагаю, чтобы скомпилировать примеры (с gcc -Wall -g
), а затем запустить их шаг за шагом в gdb
отладчика. Используйте часто display
, step
, backtrace
, frame
commandsgdb
.
@ Илья Я думаю, что редактирование кода в соответствии с вашим соглашением, вероятно, не самое лучшее, что нужно делать, и не следует правилам SO .... – tomsoft
@tomsoft, спасибо вам, отзыв! Я снова прочитаю правила SO. (для меня было трудно прочитать начальную версию вопроса, поэтому я решил улучшить его, но может быть, это было неправильное решение. Спасибо!) – Ilya