Главная » Алгоритмы » Локальные функции

0

Локальной или вложенной называется процедура или функция, описанная внутри другой процедуры (функции). Она может иметь свои локальные пе­ременные, а может и обращаться к переменным функции, внутри которой она описана. Вызывать ее можно только из функции, внутри которой она описана, т. е. область видимости ограничена родительской функцией.

Основным недостатком языка С при программировании шахмат является именно отсутствие в нем локальных функций. Вот пример локальной функ­ции (процедуры) на паскале:

procedure Foo(argl,arg2:integer); procedure SubFoo(arg3,arg4:integer); begin

{…}

end; begin

{…}

end;

В функции Foo можно вызвать процедуру SubFoo, которая может обращаться к переменным argl, arg2 вызывающей ее функции foo. Почему в С нет ло­кальных функций? Трудно сказать. В языке С первоначально много чего не было. Видимо, основная причина заключается в том, что это считается не­системной вещью, т. к., чтобы обратиться к переменным родительской функции, SubFoo должна извлечь из стека регистр вр(евр), а проще говоря, указатель на эти переменные. Тем не менее это очень удобный прием. В некоторых версиях компиляторов С можно эмулировать локальную функ­цию на ассемблере (если она не имеет своих аргументов):

void Foo(int argl, int arg2) {

SubFoo: //метка {…}

_asm ret; //возврат из подпрограммы (…) //инструкции функции Foo

_asm call SubFoo; //вызов вложенной подпрограммы }//function

Этот прием, тем не менее, является довольно опасным. Нужно очень четко представлять, какие регистры нужно сохранить в локальной процедуре, и, кроме того, разработчики некоторых компиляторов очень активизируются в данных случаях, и нет гарантии, что это будет работать, раз не предусмот­рено синтаксисом языка. Гораздо проще оформить переменные (стековые) функции Foo в виде структуры, а в SubFoo передавать указатель на эту струк­туру.

typedef struct!

int argl,arg2; }Targ.*Parg;

void SubFoo(Parg arg) {

{…}

}

vois Foo(Parg arg) {

{ . . . }

SubFoo(arg); >

В некоторых случаях такой прием бывает чрезвычайно удобен. Функция Foo может быть очень большой и содержать множественные вызовы SubFoo, ко­торая, в свою очередь, вызывает вложенные функции следующего уровня. Передавать каждый раз огромный список параметров очень накладно, и, кроме того, локальные функции должны иметь возможность изменять эти переменные. К сожалению, данный прием не улучшает читабельность про­граммы. Когда-нибудь в С появятся локальные функции (как и нормальный строковый тип данных).

Литература:

Корнилов Е. Н.  Программирование шахмат и других логических игр. — СПб.: БХВ-Петербург, 2005. – 272 е.: ил.

По теме:

  • Комментарии