Автоматические переменные образуются и исчезают одновременно с входом в функцию и выходом из нее, они не сохраняют своих значений от вызова к вызову и должны устанавливаться заново при каждом новом обращении к функции.
В качестве альтернативы автоматическим переменным можно определить внешние переменные, к которым разрешается обращаться по их именам из любой функции. Так как внешние переменные доступны повсеместно, их можно использовать вместо аргументов для связи между функциями по данным. Кроме того, поскольку внешние переменные существуют постоянно, а не возникают и исчезают на период выполнения функции, свои значения они сохраняют и после возврата из функций, их установивших.
Внешняя переменная должна быть определена, причем только один раз, вне текста любой функции; в этом случае ей будет выделена память. Она должна быть объявлена во всех функциях, которые хотят ею пользоваться. Объявление может быть явным, в виде инструкции extern, или неявным, когда нужная информация получается из контекста. Чтобы конкретизировать сказанное, авторы книги предлагают переписать программу печати самой длинной строки с использованием line, longest и max в качестве внешних переменных. Это потребует изменений в вызовах, объявлениях и телах всех трех функций.
#define MAXLINE 1000 /* максимальный размер вводимой строки */
int max; /* длина максимальной из просмотренных строк */
char line[MAXLINE]; /* текущая строка */
char longest[MAXLINE]; /* самая длинная строка */
int getstr(void);
void copy(void);
/* печать самой длинной строки; специализированная версия */
int main(void)
{
int len;
extern int max;
extern char longest[];
max = 0;
while ((len = getstr()) > 0)
if (len > max)
{
max = len;
copy();
}
if (max > 0) /* была ли хоть одна строка */
printf("%s", longest);
return 0;
}
/* getstr: специализированная версия */
int getstr(void)
{
int c, i;
extern char line[];
for (i = 0; i < MAXLINE - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
line[i] = c;
if (c == '\n')
{
line[i] = '\n';
++i;
}
line[i] = '\0';
return i;
}
/* copy: специализированная версия */
void copy(void)
{
int i;
extern char line[], longest[];
i = 0;
while ((longest[i] = line[i]) != '\0')
++i;
}
$ vim longest.c#include <stdio.h>
#define MAXLINE 1000 /* максимальный размер вводимой строки */
int max; /* длина максимальной из просмотренных строк */
char line[MAXLINE]; /* текущая строка */
char longest[MAXLINE]; /* самая длинная строка */
int getstr(void);
void copy(void);
/* печать самой длинной строки; специализированная версия */
int main(void)
{
int len;
extern int max;
extern char longest[];
max = 0;
while ((len = getstr()) > 0)
if (len > max)
{
max = len;
copy();
}
if (max > 0) /* была ли хоть одна строка */
printf("%s", longest);
return 0;
}
/* getstr: специализированная версия */
int getstr(void)
{
int c, i;
extern char line[];
for (i = 0; i < MAXLINE - 1 && (c = getchar()) != EOF && c != '\n'; ++i)
line[i] = c;
if (c == '\n')
{
line[i] = '\n';
++i;
}
line[i] = '\0';
return i;
}
/* copy: специализированная версия */
void copy(void)
{
int i;
extern char line[], longest[];
i = 0;
while ((longest[i] = line[i]) != '\0')
++i;
}
$ cc -g -O0 -Wall -o a.out longest.c
Внешние переменные для main, getstr и copy определяются в начале примера, где им присваивается тип и выделяется память. Определения внешних переменных синтаксически ничем не отличаются от определения локальных переменных, но поскольку они расположены вне функций, эти переменные считаются внешними. Чтобы функция могла пользоваться внешней переменной, ей нужно прежде всего сообщить имя соответствующей переменной. Объявления внешней переменной начинается с ключевого слова extern.
В некоторых случаях объявление extern можно опустить. Если определение внешней переменной в исходном файле расположено выше функции, где она используется, то в объявлении extern нет необходимости. Таким образом, в main, getstr и copy объявления extern избыточны. Обычно определения внешних переменных располагают в начале исходного файла, и все объявления extern для них опускают.
Если же программа расположена в нескольких исходных файлах и внешняя переменная определена в файле1, а используется в файле2 и файлеЗ, то объявления extern в файле2 и файлеЗ обязательны, поскольку необходимо указать, что во всех трех файлах функции обращаются к одной и той же внешней переменной. На практике обычно удобно собрать все объявления внешних переменных и функций в отдельный файл, называемый заголовочным (header-файлом), и помещать его с помощью #include в начало каждого исходного файла.
Добрый день. хорошая статья!
ОтветитьУдалитьА если есть локальная переменная в одной функции, в другой функции можно ее использовать если использовать ключевое слово extern?