Руководство полного чайника по программированию на языке Си


СТЕК И ФУНКЦИИ


Будем рассматривать каждый ВЫЗОВ функции как помещение в специальный стек большого "блока информации", включающего в частности АРГУМЕНТЫ И ЛОКАЛЬНЫЕ ПЕРЕМЕННЫЕ вызываемой функции.

Оператор return из вызванной функции выталкивает со стека ВЕСЬ такой блок.

В качестве примера рассмотрим такую программу:

int x = 7; /* глобальная */ int v = 333; /* глобальная */

int factorial(int n){ int w; /* лишняя переменная, только для демонстрационных целей */

w = n;

if(n == 1) return 1; /* #a */ else return n * factorial(n-1); /* #b */ } void func(){ int x; /* func::x */

x = 777; /* #c */ printf("Вызвана функция func()\n"); } void main(){ int y = 12; /* main::y */ int z;

/* A */ z = factorial(3); /* B */ printf("z=%d\n", z);

func(); /* C */ }

Выполнение программы начнется с вызова функции main(). В точке /* A */

| в з г л я д | V V

--------+ +-------- |=======================| | z = мусор | | y = 12 | +------+---------+ |main() | |x = 7 | v = 333 | +-----------------------+-----------+------+---------+----- СТЕК ВЫЗОВОВ ФУНКЦИЙ ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ

В каждый данный момент видимы переменные, которые находятся a) на вершине (и только) стека вызовов функций. b) и незаслоненные ими глобальные переменные. В данном случае мы смотрим "сверху" и видим:

main::z, main::y, ::x, ::v

В точке /* B */ мы вызываем factorial(3).

--------+ +-------- |=======================| | w = мусор | | n = 3 | |factorial(3) | |=======================| | +-|---> текущий оператор z = factorial(3); | z = мусор | | y = 12 | +------+---------+ |main() | |x = 7 | v = 333 | +-----------------------+-----------+------+---------+----- СТЕК ВЫЗОВОВ ФУНКЦИЙ ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ

При новом взгляде видимы: factorial(3)::w, factorial(3)::n, ::x, ::v

Стали невидимы: main::z, main::y

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

Когда выполнение программы в функции factorial(3) дойдет до точки /* #b */ будет выполняться return 3 * factorial(2). В итоге будет вызвана функция factorial(2).




- Начало -  - Назад -  - Вперед -