Шаг 51.
Внешний класс памяти (extern)

    Этот шаг посвящен особенностям использования класса памяти extern.

    Oбъекты, описанные внутри функции с добавлением класса памяти extern, либо описанные вне функции без указания класса памяти, относятся к внешним объектам.

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

    Сами функции также являются внешними объектами, поскольку правила языка C++ не позволяют определять одни функции внутри других.

    Внешние переменные можно инициализировать только выражениями с константами и указателями на ранее описанные объекты. По умолчанию (если не задана инициализация) внешние объекты получают нулевые начальные значения.


    Пример 1.
#include <iostream.h>
int i;         /* Определение i */
int j=100;     /* Определение j */
void main ()
   {
      extern int i;  /* Описание i */
      extern int j;  /* Описание j */
      /* ------------------------- */
      cout << "i = " << i << endl;
      cout << "j = " << j << endl;
   }
Текст этой программы можно взять здесь.

    Результаты работы программы:

   i=0
   j=100

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

    Например, появившиеся вне определения какой-либо функции строчки

   int max;
   char save [maxline];

определяют внешние переменные max и save, вызывают отведение для них места в памяти.

    В то же время строчки

   extern int max;
   extern char save[];

описывают в данном блоке переменную max как int, a save как массив типа char (размеры которого указаны в другом месте программы), но не создают переменных и не отводят для них места в памяти.

    Во всех файлах, составляющих исходную программу, должно содержаться только одно определение внешней переменной; другие файлы могут содержать описания extern для доступа к ней.

    Любая инициализация внешней переменной производится только в определении. Для внешних переменных инициализация выполняется только один раз, на этапе компиляции.


    Пример 2. Разберем, что напечатает следующая программа и почему.
#include <iostream.h>
int i=0;
   /* Класс памяти переменной - внешний.           */
   /* Область действия переменной - все файлы,     */
   /* содержащие данную программу. Время существо- */
   /* вания i=0 - все время выполнения программы.  */
void main ()
{
   auto int i=1;                 /* Блок уровня 1 */
   /* В блоке 1 область действия i=1 - функция    */
   /* main(). Время существования i=1 - все время */
   /* выполнения главной функции main().          */
   cout << i << endl;
   /* Если две переменные имеют одно и то же имя, */
   /* то по этому имени обращаются к внутренней   */
   /* переменной, внешняя непосредственно недос-  */
   /* тупна, поэтому после выполнения блока 1 про-*/
   /* грамма напечатает 1.                        */
   /* ------------------------------------------- */
   cout << ::i << endl;
   /* При необходимости получить доступ к внешней */
   /* переменной используют операцию области ви-  */
   /* димости. Поэтому здесь будет напечатан 0.   */
   /* ------------------------------------------- */
   {                             /* Блок уровня 2 */
    int i=2;
    /* Класс памяти переменной i=2 - auto.  */
    /* Область действия i=2 - блок 2, время */
    /* существования - время существования  */
    /* блока 2.                             */
    cout << i << endl;
    /* Программа напечатает 2.                  */
    /* ---------------------------------------- */
    cout << ::i << endl;
    /* Тоже будет напечатан 0, так как используя*/
    /* операцию области видимости можно получить*/
    /* доступ только ко внешней переменной.     */
    /* -----------------------------------------*/
    {                          /* Блок уровня 3 */
       i += 1; cout << i << endl;
      /* Печатается значение самой  внутренней пере- */
      /* менной с именем i, которая после выполнения */
      /* операции данного блока становится  равной 3 */
    }
    /* Возвращение к блоку уровня 2 */
    cout << i << endl;
    /* Опять печатается 3 */
   }
   /* Возвращение к блоку уровня 1 */
   cout << i << endl;
   /* Переменная i=3 из  блока уровня 2 исчезает. */
   /* Теперь самой внутренней переменной с именем */
   /* i будет  i=1.                               */
 }
Текст этой программы можно взять здесь.

    Внешние объекты делятся на внешние глобальные и внешние статические.

    На следующем шаге мы познакомимся с внешними глобальными объектами.


Предыдущий шаг Содержание Следующий шаг