Р.У. Себеста - Основные копцепции языков программирования (2001) (1160794), страница 100
Текст из файла (страница 100)
разрабатывемые для таких приложений, должны допускать такой вид компиляции. Имея такую возможность, программист при разработке или эксплуатации системы может перекомпилировать только те ее молули, которые подверглись изменениям. Как заново, так и ранее скомпилированные модули собираются в одно целое программой, называемой редактором связей, которая является частью операционной системы. Если бы такой возможности не было„то прн каждом изменении системы потребовалась бы полная перекомпиляция.
Для больших систем зто было бы слишком дорого. 380 Глава 8. Подпрограммы 3 этом разделе мы обсудим два разных подхода к компиляции частей программы, на- зэечых раздельной компиляцией и независимой компиляцией. Части программ, кото-.: е чогут компилироваться отдельно, иногда называются единицами компиляции. , ермин раздельная компиляция (зерагаГе сошрйагюп) означает, что единицы комиц.: ии могут компилироваться в разное время, но при этом процессы их компиляции зави::- лруг от друга, если единицы компиляции имеют доступ к каким-либо сущностям дру"з единиц компиляции или используют их. Такая взаимозависимость нужна при проверке -терфейса.
Сначала мы обсудим раздельную компиляцию в контексте языка Аба. Зля належной раздельной компиляции некоторого модуля компилятор должен иметь з.ст) и к информации о сущностях программы (переменных, типах и протоколах подпро—.зчч). которые используются в данном модуле, но объявлены где-то в другом месте. шности пакета на языке Ада, видимые в других модулях, называются экспортируемы,. Информация о таких сущностях образует интерфейс пакета. Напомним, что протокол -эоцедуры включает в себя количество. имена и типы ее параметров, вместе с порядком, : котором они появляются.
В протокол функции также включается тип возвращаемого -эчення. Системы реазизации языка Ада хранят информацию об интерфейсе модуля в -.. ступной компилятору библиотеке. Информация об интерфейсе помещается в библио-еку при каждой компиляции. В библиотеках хранятся библиотечные модули, представляющие собой уже скомпи-чрованные единицы компиляции. В языке Ада единицами компиляции являются заю-. вки подпрограмм, объявления пакетов (см. главу 10) и тела подпрограмм.
Во время компиляции программного модуля на языке Аба все используемые сушно:-и. объявленные вне данного модуля. подвергаются проверке на совместимость типов. :-' подпрограммах проверка совместимости типов выполняется для всего протокола. °:нкретной программной единице компиляции доступна не вся информация, храняшаяа библиотеке. Имена тех программных модулей, в которых находятся нужные внеш-не сущности, перечисляются в операторе иди в начале модуля, подлежащего компигчции.
Используя оператор ч(с)з, программист указывает внешние сущности, к которым элжен иметь доступ компилируемый код. Например, приведенная ниже процедура ис-. льзует сущности, находящиеся в двух внешних модулях СЬОВАЬВ и ТЕХТ 10, и. сле=; вательно, указывает их: чзчуг ОЕОВАЕВ, ТЕХТ 10~ ркосвс(икв ЕХАМРЕЕ зв впг( ЕХАМРЬЕ; Язык Мог!о!а-2 обеспечивает раздельную компиляцию таким же способом. Язык гОКТКАН 90 также допускает раздельную компиляцию своих подпрограмм и модулей. 'эздельная компиляция в языке Аоа будет обсуждаться более детально в главе 10 после -. го. как мы рассмотрим возможности абстракции данных в этом языке.
В некоторых языках, среди которых выделяются языки С и РОСТКАМ 77, допускаетя независимая компиляция. При независимой компиляции (!пдерепдепг сотр11а!1оп) "рограммные модули можно компилировать без информации о каких-либо еше прорамчных единицах. Наиболее важное свойство независимой компиляции заключается в том. что интерфей;ы чежду отдельно компилируемыми людулями не подвергаются проверке на совместичисть типов.
Интерфейс подпрограммы на языке ГОКТКА1Ч 77 представляет собой список 8.9. Раздельная и независимая компиляция параметров. Когда подпрограмма компилируется отдельно. типы ее параметров не хранятся вместе с компилируемым кодом или в библиотеке. Следовательно, при компиляции другой программы, вызывающей данную подпрограмму, типы фактических параметров в вызове не могут проверяться на совместимость с типами формальных параметров подпрограммы, даже если доступен машинный код вызываемой подпрограммы. Для языка ГОКТКАН 77 это не удивительно.
Даже когда программа, вызывающая некую подпрограмму, и сама эта подпрограмма компилируются в одном и том же файле, они, по существу, компилируются независимо. Таким образом, интерфейс между программными модулями на языке ГОКТКАН 77 никогда не проверяется на совместимость типов. Некоторые языки не допускают ни раздельной, ни независимой компиляции. Это означает, что единственной единицей компиляции является полная программа.
К таким языкам относятся язык ГОКТКАХ Н и исходная версия языка Рааса!. Отсутствие как раздельной, так и независимой компиляции очень сильно ограничивает язык, делая фактически невозможным его промышленное использование. Совершенно ясно, что лучше иметь возможность независимой компиляции, чем совсем не иметь возможности компилировать отдельные части программы, хотя при этом не происходит проверка интерфейсов программных модулей на совместимость типов. В более поздних версиях языков ГОКТКАН и Рааса! это недостаток был устранен. 8.10.
Вопросы разработки функций Для функций характерны следующие вопросы разработки. ° Допускаются ли побочные эффекты? ° Значения каких типов могут возвращаться функциями? 8.10.1. Побочные зффекты функций Вследствие побочных эффектов, которые характерны для функций, вызываемых в выражениях, как описано в главе 4, параметры в функции должны передаваться в режиме ввода. Некоторые языки фактически требуют выполнения этого условия; например, функции в языке Ада могут иметь только формальные параметры, передаваемые в режиме ввода. Зто эффективно предотвращает появление побочных эффектов при передаче параметров или при возникновении совмещения имен параметров и глобальных переменных. В большинстве других языков, однако, функции могут иметь параметры, передаваемые либо по значению, либо по ссылке, допуская, таким образом, как побочные эффекты, так и совмещение имен.
8.10.2. Типы возвращаемых значений В большинстве императивных языков программирования типы переменных, которые могут возвращаться функциями, ограничены. В языках ГОКТКАХ 77, Рааса! и Мог!ц!а-2 функции могут возвращать только неструктурированные типы. В языке С функции возвращают переменные любого типа, кроме массивов и функций.
Однако в языке С функции могут возвращать указатели как на массивы, так и на функции. Язык С++ похож на язык С, однако в нем функции могут возвращать также переменные определенных пользователем типов, или объекты классов. Язык Аг!а — единственный среди современных императивных языков, в котором функции могут возвращать переменные любого типа.
332 Глава 8. Подпрограммы 8.11. Доступ к нелокалй ным средам Несмотря на то что в основном связь между подпрограммами может осуществляться .срез параметры, в большинстве языков предусмотрен еще один способ доступа к пере° енныч — через внешние среды. Нелокальные переменные (поп!оса! чапаЫез) подпрограммы — это те переменные, вторые видимы в подпрограмме, но не объявлены в ней локально. Глобальные переменные (я!оЬа! чайаЫез) — это те переменные, которые видимы во всех модулях про. зчмы.
В главе 4 обсуждались два метода доступа к нелокальным переменным; стати-ескнй обзор н динамический обзор. Проблемы разработки этих способов рассматрива-. тся ниже. Основная проблема, связанная с применением статическою обзора данных для соэчестного использования иелокальных переменных, состоит в следующем: структура -ро~раммы определяется главным образом лоступностью локальных и глобальных перечеиных другим подпрограммам, а не хорошо продуманными проектными решениями.
:-:роме того, во всех случаях для доступа к нелокальиым переменным предоставляется ".эльше возможностей, чем требуется. Примеры, иллюстрирующие эту проблему, приве:ены в главе 4. Динамический обзор данных порождает два вида проблем. Во-первых, в промежутке времени от начала и до завершения выполнения подпрограммы локальные переменные «вляются видимыми лля любой другой выполняемой подпрограммы, независимо от того, -зсколько близки эти подпрограммы по своему содержанию. Не существует способа заиты локальных переменных от такого доступа. Подпрограммы всегда выполняются в -епосредственном окружении вызывающего модуля. Вследствие этого динамический . бюр данных приводит к менее надежным программам.
чем статический. Вторая проблема, связанная с динамическим обзором, — невозможность статической троверки совместимости типов ссылок на нелокальные переменные, поскольку невозчо кно статически обнаружить объявление такой переменной. Реализация доступа к нелокальным переменным детально обсуждается в главе 9. В.11.1. Блоки сонмом языка ГОВтаАМ В языке РОКТЕАХ доступ к блокам, в которых хранятся глобальные переменные, ;) шествляется через оператор СОММОЙ. В программе может быть сколько угодно таких . оков, и все, кроме одного из них, должны иметь имя. (Один неименованный блок .:С:ОИ, часто называемый пустым блоком СОНМОМ, обладает иными свойствами по .гзвнению с именованными СОММОЙ-блоками.) Любая подпрограмма, в которой следует - лучить доступ к блоку СОММОМ или создать его, содержит оператор СОММОИ, име-..ющий этот блок и задающий список переменных для доступа к содержимому этого =гока.
Блок СОММОМ создается в тот момент, когда компилятор находит первый оператор .:.'ОМ, задающий имя данного блока. В программе допускается неограниченное количество подпрограмм, которые могут : 'держать оператор СОММОМ, указывающий один и тот же блок. Далее, каждая подпро=зима, в которой указан данный блок, может определять свой собственный список пегеменных, по количеству и типам переменных никак не связанный со списками перееииых в других подпрограммах. Например, в рамках одной программы один и тот же звз 3.1 1.
Доступ к нелокальным средам блок в разных подпрограммах можно объявлять по-разному. Пусть в первой подпрограмме содержатся следующие объявления: КЕА1 А(100) 1МТЕ6ЕВ В(250) СОММОМ /ВЬОСК1/ А, В В другой подпрограмме объявления могут быть иными: КЕАЬ С(50), 0(100) 1МТЕОЕК Е(200) СОММОМ /ВЬОСК1/ С, О, Е Идентификатор ВЬОСК1, отделенный косыми чертами, представляет собой имя блока. Две точки зрения на переменные в блоке ВЬОСК1 показаны на рис. 8.3.