Заглавная страница Избранные статьи Случайная статья Познавательные статьи Новые добавления Обратная связь КАТЕГОРИИ: АрхеологияБиология Генетика География Информатика История Логика Маркетинг Математика Менеджмент Механика Педагогика Религия Социология Технологии Физика Философия Финансы Химия Экология ТОП 10 на сайте Приготовление дезинфицирующих растворов различной концентрацииТехника нижней прямой подачи мяча. Франко-прусская война (причины и последствия) Организация работы процедурного кабинета Смысловое и механическое запоминание, их место и роль в усвоении знаний Коммуникативные барьеры и пути их преодоления Обработка изделий медицинского назначения многократного применения Образцы текста публицистического стиля Четыре типа изменения баланса Задачи с ответами для Всероссийской олимпиады по праву Мы поможем в написании ваших работ! ЗНАЕТЕ ЛИ ВЫ?
Влияние общества на человека
Приготовление дезинфицирующих растворов различной концентрации Практические работы по географии для 6 класса Организация работы процедурного кабинета Изменения в неживой природе осенью Уборка процедурного кабинета Сольфеджио. Все правила по сольфеджио Балочные системы. Определение реакций опор и моментов защемления |
Классы хранения и видимость переменных
Общие положения
Для каждого идентификатора существует как минимум два атрибута: тип и класс хранения. Тип определяет размер памяти, выделяемой компилятором для объекта и способ интерпретации выделенной памяти (например, как адрес памяти для указателей или массив однотипных элементов). Класс хранения определяет место, где объект располагается (внутренние регистры процессора, сегмент данных, сегмент стека), и одновременно время жизни объекта (например, все время выполнения программы или только время выполнения конкретной части кода программы). Класс хранения либо задается явно, либо компилятор «сам» определяет это по местоположению описания в тексте программы. Время жизни и класс хранения тесно связаны друг с другом. С точки зрения времени жизни различают три типа объектов: статические, локальные, динамические. Тесно связанным с понятием «класс хранения» является и понятие видимости, или области определения идентификатора. Область определения - это та часть программы, в пределах которой идентификатор может использоваться для доступа. Есть несколько типов области определения: в пределах блока (локальная видимость); в пределах функции; в пределах файла текста программы.
7.2. Область определения и видимость идентификатора.
Внешние переменные
Текст программы на С++ может быть размещен целиком в одном текстовом файле, в котором будут помещены функция main() и все другие функции, если они есть. Однако это не всегда удобно (а иногда и просто невозможно). В таком случае текст программы размещается в нескольких текстовых файлах, каждый из которых содержит целиком одну или несколько функций. Для объединения в одну программу эти текстовые файлы компилируются совместно. Информация (имя текстового файла, директорий) обо всех объединяемых в одну программу файлах, может быть помещена в так называемый файл проекта. Компилятор порождает для каждого исходного текстового файла отдельный объектный файл. Затем эти файлы объединяются компоновщиком в загрузочный модуль (.EXE-файл). Объектный файл - это неготовый к исполнению программный код. Образно говоря, объектный файл - это отдельный модуль дорогого музыкального центра, состоящего из отдельных блоков: усилителя, радиоприемника, магнитофона, проигрывателя. Для того, чтобы «заиграла» музыка, необходимо эти блоки соединить проводами друг с другом. Чтобы не ошибиться, разъемы на разных сторонах проводов часто делают неодинаковыми. Разъемы в объектных файлах порождает компилятор. Один вид разъемов соответствует известному в языке ассемблера понятию PUBLIC, другой - понятию EXTERN. Процесс объединения блоков с помощью проводов похож на работу компоновщика. В роли разъемов, объединяемых в объектных файлах проводами, выступают так называемые внешние ссылки. Это либо имена функций, либо переменные. Встретив разъем EXTERN, компоновщик ищет подходящий ему разъем PUBLIC сначала в данном объектном файле, затем в других объектных файлах из числа компилируемых совместно. Потом он просматривает библиотеки. Если подходящий разъем не найден, компоновка завершается с сообщением об ошибке типа «Неразрешенная внешняя ссылка» или «неизвестное имя...» (Unresolved external …).
Если разъем EXTERN соответствует имени библиотечной функции, то она помещается в загрузочный модуль. Другими словами, разъем EXTERN - это указание компоновщику искать соответствующий ему по имени разъем типа PUBLIC. Область определения идентификатора нужна компилятору для того, чтобы сгенерировать корректный машинный код. Если идентификатор описан внутри блока {}, он имеет локальную область определения, ограниченную размерами блока. Отсюда следует, что все переменные, описанные внутри функции, в том числе и формальные параметры, имеют локальную область определения. Для локальных переменных компилятор не создает никаких разъемов – ни PUBLIC, ни EXTERN. Если идентификатор описан вне каких-либо блоков, он является глобальным и имеет область определения, начинающуюся с точки описания и продолжающуюся до конца файла. Для всех глобальных переменных компилятор создает разъем PUBLIC. Глобальный идентификатор будет видимым из всех функций ниже точки описания переменной. Чтобы идентификатор стал видимым в функциях выше точки описания переменной или в функциях, определения которых расположены в других файлах, используется объявление с атрибутом EXTERN. Обратите внимание на то, что воздействие на видимость объекта не связано с резервированием памяти компилятором. Поэтому, например, строка программы
extern int var1; является не описанием переменной, а объявлением ее как внешней ссылки. Обрабатывая такое предложение, компилятор создает разъем EXTERN для переменной var1. Отсюда вытекают два очевидных следствия: при объявлении переменной как EXTERN просто невозможно выполнить ее инициализацию. Например, выражение extern int var1 = 20; является ошибкой; для того чтобы какой-либо объект данных, в том числе и объявленный как EXTERN, был видим из всех функций файла, необходимо поместить описание или объявление объекта в самом начале файла, перед первой функцией. Сначала компоновщик просматривает глобальные переменные текущего файла (т.е. все разъемы PUBLIC в том файле, в котором встретилось объявление EXTERN). Если не найден подходящий глобальный идентификатор в текущем файле, компоновщик просматривает все идентификаторы, помеченные как PUBLIC, в других объектных файлах, образующих один проект. Если и там не будет найден соответствующий идентификатор, поиск продолжается в библиотеках. Внешние переменные – один из способов «передачи» функциям аргументов и «возврата» из функций необходимых значений. Просто взаимодействующие функции используют общие области памяти. Имена функций в языке С++ – это всегда глобальные имена, видимые по умолчанию из всех файлов одного проекта. Однако прототип функции действует только в пределах одного файла. Из-за этого, в частности, приходится помещать во все совместно компилируемые файлы директивы препроцессора, связанные с подключением.h-файлов, содержащих прототипы библиотечных функций. Приведем пример программы, текст которой размещен в двух файлах (для связи функций программы используется внешняя переменная i): // Prim7_1.cpp #include <stdio.h> extern int i; void main(void) { void next(void); /* прототип */ int i = 3; i++; printf("В main i = %d\n", i); next(); } void next(void) { void other(void); /* прототип */ i++; printf("B next i = %d\n", i); other(); }
// Prim7_2.cpp #include <stdio.h> extern int i; void other(void) { i++; printf("B other i = %d\n", i); } В результате выполнения программы получены следующие результаты: B main i = 4 B next i = 5 B other i = 6
|
||||||
Последнее изменение этой страницы: 2017-02-05; просмотров: 257; Нарушение авторского права страницы; Мы поможем в написании вашей работы! infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.134.76.51 (0.01 с.) |