Правила программирования на Си и Си++

       

Никогда не требуйте инициализации глобальной переменной при вызове функции


Вот одна ситуация, где оправданы статические глобальные переменные: если у вас применяется система рекурсивных функций. (Вы можете использовать статические глобальные переменные для сокращения потребного объема стековой памяти, применяя их для передачи значений между подпрограммами. Вам никогда не нужно использовать статическую глобальную переменную для передачи информации из одной подпрограммы в другую, являющуюся рекурсивным экземпляром той же самой подпрограммы. Верным выбором в этой ситуации будет использование локальной статической переменной. Используйте статические глобальные переменные в ситуациях, где вызывается более одной подпрограммы: A()

вызывает B(), которая вызывает A(), вызывающую в свою очередь B(), и так далее).

Так как глобальная переменная, используемая нашей рекурсивной функцией, сделана статической для минимизации связывания, то как вам ее инициализировать? Далее показано, как не нужно этого делать. Вот файл 1:

static  int  glob;

get_glob( x )

{

    return glob;

}

set_glob( x )

{

    glob = x;

}

void recursive_function( void )



{

    int  y = glob;

    // ...

    recursive_function();

}

а вот файл 2:

set_glob( 10 );

recursive_function();

x = get_glob();

Вы при этом немногого достигли с точки зрения связывания; на самом деле, с простой глобальной переменной было бы проще управляться. Кроме того, вы подготовили себе потенциальную проблему: возможность забыть вызвать set_glob(). Вот как сделать это правильно:

static int

glob;

static void

recursive_function( void )

{

    int y = glob;

    // ...

    recursive_function();

}

int do_recursive( int init_val )

{

    glob = init_val;

    recursive_function();

    return glob;

}

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

do_recursive(), которая гарантирует, что все инициализировано правильно перед тем, как выполнить вызов рекурсивной функции.



Содержание раздела