Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Название:Язык программирования C. Лекции и упражнения (6-е изд.) 2015
- Автор:
- Жанр:
- Издательство:Вильямс
- Год:0101
- ISBN:нет данных
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Стивен Прата - Язык программирования C. Лекции и упражнения (6-е изд.) 2015 краткое содержание
Язык программирования C. Лекции и упражнения (6-е изд.) 2015 - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
int х = 10; // допустимо, 10 - это константа
int у=3+20; // допустимо, константное выражение
size_t z = sizeof(int); // допустимо, константное выражение int х2 = 2 * х; // недопустимо, х - это переменная
(При условии, что типом не является массив, выражение sizeof считается константным.)
Использование внешней переменной
Давайте рассмотрим простой пример, в котором задействована внешняя переменная. В частности, предположим, что две функции с именами main() и critic() должны иметь доступ к переменной units. Это можно сделать, объявив unit s за пределами ранее упомянутых двух функций, как показано в листинге 12.4. (Примечание: назначение данного примера — демонстрация работы внешней переменной, а не ее типичное применение.)
Классы хранения, связывание и управление памятью 495
Листинг 12.4. Программа global .с
Вот результаты пробного запуска:
Сколько фунтов весит маленький бочонок масла?
14
Вам не повезло. Попробуйте еще раз.
56
Вы знали это!
Обратите внимание, что второе значение для units читается функцией critic(), но main() также известно новое значение после завершения цикла while. Таким образом, и main(), и critic() используют идентификатор units для доступа к одной и той же переменной. В рамках терминологии С мы говорим, что переменная units имеет область видимости в пределах файла, внешнее связывание и статическую продолжительность хранения.
Мы сделали units внешней переменной, определив ее за пределами определений всех функций. Это и все, что необходимо сделать для обеспечения доступности units всем последующим функциям в файле.
Давайте посмотрим на некоторые детали. Прежде всего, объявление переменной units там, где оно находится, делает ее доступной объявленным далее функциям без дополнительных усилий. Следовательно, функция critics() пользуется переменной
units.
Аналогично, ничего не придется предпринимать для предоставления доступа к units функции main(). Однако в main() имеется такое объявление:
extern int units;
В рассматриваемом примере это объявление является главным образом формой документирования. Спецификатор класса хранения extern сообщает компилятору, что любое упоминание units в данной функции относится к переменной, объявленной за пределами этой функции, возможно, даже вне самого файла. И снова main() и critic() работают с внешне определенной переменной units.
496 глава 12
Внешние имена
Стандарты С99 и С11 требуют, чтобы компиляторы распознавали первые 63 символа для локальных идентификаторов и первые 31 символ для внешних идентификаторов. Это корректирует предыдущее требование по распознаванию первых 31 символа для локальных и первых 6 символов для внешних идентификаторов. Вполне возможно, что вы имеете дело со старыми правилами. Причина того, что правила для имен внешних переменных являются более ограничивающими, чем правила для имен локальных переменных, связана с тем, что внешние имена должны подчиняться правилам локальной среды, которые могут быть более жесткими.
Определения и объявления
А теперь давайте внимательнее посмотрим на отличие между определением переменной и ее объявлением. Взгляните на следующий пример:
int tern =1; /* переменная tern определена */
main()
{
external int tern; /‘использование tern, определенной где-то в другом месте*/
Здесь переменная tern объявлена дважды. Первое объявление приводит к тому, что для переменной отводится место в памяти. Оно образует определение переменной. Второе объявление просто указывает компилятору на необходимость применения переменной tern, которая была создана ранее, так что это не определение. Первое объявление называется определяющим объявлением, а второе — ссылочным объявм- ннем. Ключевое слово extern говорит о том, что объявление не является определением, т.к. оно инструктирует компилятор искать определение где-то в другом месте. Предположим, что вы записали следующий код:
extern int tern; int main(void)
{
Компилятор предположит, что действительное определение tern находится в другом месте программы, возможно, в другом файле. Это объявление не приводит к выделению пространства в памяти. Таким образом, не используйте ключевое слово extern для создания внешнего определения; применяйте его только для ссылки на существующее внешнее определение.
Внешняя переменная может быть инициализирована только один раз, и это должно делаться при определении переменной. Взгляните на следующий код:
// файл one.с char permis = 'N';
// файл two. с
extern char permis = 'У; /* ошибка */
Ошибка заключается в том, что определяющее объявление в файле one.с уже было создано, и оно инициализировало переменную permis.
Статические переменные с внутренним связыванием
Переменные с этим классом хранения имеют статическую продолжительность хранения, область видимости в пределах файла и внутреннее связывание. Такая переменная создается путем ее определения вне любых функций (как и в случае внешней переменной) с указанием спецификатора класса хранения static:
Классы хранения, связывание и управление памятью 497
static int svil = 1; // статическая переменная, внутреннее связывание
int main(void)
{
Переменные подобного рода когда-то получили название внешних статистических переменных, но это слегка запутывает, т.к. они имеют внутреннее связывание. К сожалению, новый компактный термин найти не удалось, поэтому нам остается вариант статическая переменная с внутренним связыванием. Обычная внешняя переменная может использоваться функциями в любом файле, который является частью программы, но статическая переменная с внутренним связыванием может применяться только функциями в том же самом файле. Внутри функции можно повторно объявить любую переменную с областью видимости в пределах файла, используя спецификатор класса хранения extern. Такое объявление не изменяет тип связывания. Рассмотрим следующий код:
int traveler = 1; static int stayhome = 1; int main()
{
extern int traveler; extern int stayhome;
Переменные traveler и stayhome являются глобальными в этой конкретной единице трансляции, но только traveler можно применять в других единицах трансляции. Два объявления, использующих extern, документируют тот факт, что в main() применяются две глобальных переменных, но stayhome продолжает иметь внутреннее связывание.
Множество файлов
Отличие между внутренним и внешним связыванием важно только в ситуации, когда программа строится из нескольких единиц трансляции, поэтому давайте кратко рассмотрим данную тему.
Сложные программы на С часто состоят из нескольких отдельных файлов исходного кода. Иногда в этих файлах возникает необходимость совместного использования какой-то внешней переменной. Чтобы сделать это в С, необходимо предусмотреть определяющее объявление в одном файле и ссылочные объявления в остальных файлах. Это значит, что во всех объявлениях кроме одного (определяющего объявления) должно присутствовать ключевое слово extern, а для инициализации переменной должно применяться только определяющее объявление.
Читать дальшеИнтервал:
Закладка: