482 глава 12
коде имеют область видимости в пределах блока, простирающегося до закрывающей фигурной скобки:
double blocky(double cleo)
{
double patrick = 0.0; return patrick;
}
Переменные, объявленные во внутреннем блоке, получают область видимости, ограниченную только этим блоком:
double blocky(double cleo)
{
double patrick = 0.0; int i;
for (i = 0; i < 10; i++)
{
double q = cleo * i; // начало области видимости для q patrick *= q;
} // конец области видимости для q
return patrick;
}
В этом примере область видимости q ограничена внутренним блоком, и доступ к q может иметь только код вггутри этого блока.
По традиции переменные с областью видимости в пределах блока должны объявляться в начале блока. В стандарте С99 это требование было ослаблено, и переменные разрешено объявлять в любом месте блока. Одна из новых возможностей связана с объявлением внутри управляющего раздела цикла for. То есть теперь можно поступать так:
for (int i = 0; i < 10; i++)
printf("Возможность C99: i = %d", i);
Как часть этой новой возможности, стандарт С99 расширил концепцию блока путем включения в нее кода, управляющего циклами for, while, do while или оператором if, даже если фигурные скобки при этом не используются. Таким образом, в предыдущем цикле for переменная i считается частью блока цикла for. Следовательно, ее область видимости ограничена циклом for. После того, как выполнения покинет цикл for, эта переменная i больше не видна программе.
Область видимости в пределах функции применяется только к меткам, применяемым с операторами goto. Это означает, что если метка впервые появляется во внутреннем блоке функции, ее область видимости простирается на всю функцию. Если бы можно было использовать одну и ту же метку внутри двух отдельных блоков, возникла бы путаница, поэтому область видимости в пределах функции для меток предотвращает такую ситуацию.
Область видимости в пределах прототипа функции применяется к именам переменных, используемым в прототипах функций, как в следующем случае:
int mighty (int mouse, double large);
Область видимости в пределах прототипа функции распространяется от места определения переменной до конца объявления прототипа. Это значит, что при обработ-
Классы хранения, связывание и управление памятью 483
ке аргумента прототипа функции компилятор интересует только тип аргумента. Если указаны имена, то обычно они не играют никакой роли и не обязательно должны совпадать с именами, которые применяются в определении функции. Имена играют небольшую роль в случае параметров, имеющих типы массивов переменной длины:
void use_a_VLA(int n, int m, ar[n] [m] );
При использовании имен в скобках это должны быть имена, объявленные ранее в прототипе.
Переменная, определение которой находится за рамками любой функции, имеет область видимости в пределах файла. Переменная, располагающая областью видимости в пределах файла, видна от места ее определения и до конца файла, который содержит ее определение. Взгляните на показанный ниже пример:
#include
int units = 0; /* переменная с областью видимости в пределах файла */
void critic(void); int main(void)
{
}
void critic(void)
{
}
Здесь переменная units имеет область видимости в пределах файла и может применяться и в main(), и в critic() .(Точнее, units имеет область видимости в пределах файла и внешнее связывание; отличие мы раскроем в следующем разделе.) Поскольку переменные с областью видимости в пределах файла могут использоваться в более чем одной функции, они еще называются глобальными переменными.
НА ЗАМЕТКУ! Единицы и файлы трансляции
То, что вы видите как несколько файлов, для компилятора может выглядеть как единственный файл. Предположим для примера, и это случается довольно часто, что вы включаете один или больше заголовочных файлов (с расширением.h) в файл исходного кода (с расширением .с). В свою очередь, заголовочный файл может включать другие заголовочные файлы. В итоге могут быть задействованы многие физические файлы. Однако предпроцессор С по существу заменяет директиву #include содержимым заголовочного файла. Таким образом, компилятор видит единственный файл, содержащий информацию из вашего файла исходного кода и всех заголовочных файлов. Такой файл называется единицей трансляции. Когда мы описываем переменную как имеющую область видимости в пределах файла, на самом деле она будет видимой целой единице трансляции. Если ваша программа состоит из нескольких файлов исходного кода, тогда она будет насчитывать и несколько единиц трансляции, каждая из которых соответствует файлу исходного кода и включаемым в него файлам.
Читать дальше