Чтение онлайн

на главную - закладки

Жанры

Давайте создадим компилятор!
Шрифт:

K = J + 1

CALL FOO(A, B, K)

Здесь снова требовалось копирование и это бремя ложилось на программистов. Не хорошо.

Более поздние реализации Фортрана избавились от этого, разрешив использовать выражения как параметры. Что они делали – назначали сгенерированную компилятором переменную, сохраняли значение выражения в этой переменной и затем предавали адрес выражения.

Пока все хорошо. Даже если подпрограмма ошибочно изменила значение анонимной переменной, кто об этом знал или кого это заботило? При следующем вызове она в любом случае была бы рассчитана повторно.

Проблема

возникла когда кто-то решил сделать вещи более эффективными. Они рассуждали, достаточно справедливо, что наиболее общим видом «выражений» было одиночное целочисленное значение, как в:

CALL FOO(A, B, 4)

Казалось неэффективным подходить к проблеме «вычисления» такого целого числа и сохранять его во временной переменной только для передачи через список параметров. Так как мы в любом случае передавали адрес, казалось имелся большой смысл в том, чтобы просто передавать адрес целочисленного литерала, 4 в примере выше.

Чтобы сделать вопрос более интересным большинство компиляторов тогда и сейчас идентифицирует все литералы и сохраняет их отдельно в «литерном пуле», так что мы должны сохранять только одно значение для каждого уникального литерала. Такая комбинация проектных решений: передача выражений, оптимизация литералов как специальных случаев и использование литерного пула – это то, что вело к бедствию.

Чтобы увидеть, как это работает, вообразите, что мы вызываем подпрограмму FOO как в примере выше, передавая ей литерал 4. Фактически, что передается – это адрес литерала 4, который сохранен в литерном пуле. Этот адрес соответствует формальному параметру K в самой подпрограмме.

Теперь предположите, что без ведома программиста подпрограмма FOO фактически присваивает K значение -7. Неожиданно, литерал 4 в литерном пуле меняется на -7. В дальнейшем, каждое выражение, использующее 4, и каждая подпрограмма, в которую передают 4, будут использовать вместо этого значение -7! Само собой разумеется, что это может привести к несколько причудливому и труднообъяснимому поведению. Все это дало концепции передачи по ссылке плохое имя, хотя, как мы видели, в действительности это была комбинация проектных решений, ведущая к проблеме.

Несмотря на проблему, подход Фортрана имел свои положительные моменты. Главный из них – тот факт, что мы не должны поддерживать множество механизмов. Та же самая схема передачи адреса аргумента работает для всех случаев, включая массивы. Так что размер компилятора может быть сокращен.

Частично из-за этого подводного камня Фортрана и частично просто из-за уменьшенной связи, современные языки типа C, Pascal, Ada и Modula 2 в основном передают скаляры по значению.

Это означает, что значение скаляра копируется в отдельное значение, используемое только для вызова. Так как передаваемое значение – копия, вызываемая процедура может использовать его как локальную переменную и изменять ее любым способом, каким нравится. Значение в вызывающей программе не будет изменено.

Сначала может показаться, что это немного неэффективно из-за необходимости копировать параметр. Но запомните, что мы в любом случае окажемся перед необходимостью выбирать

какое-то значение, является ли оно непосредственно параметром или его адресом. Внутри подпрограммы, использование передачи по значению определенно более эффективно, так как мы устраняем один уровень косвенности. Наконец, мы видели раньше, что в Фортране часто было необходимо в любом случае делать копии внутри подпрограммы, так что передача по значению уменьшает количество локальных переменных. В целом, передача по значению лучше.

Исключая одну маленькую деталь: если все параметры передаются по значению, у вызванной процедуры нет никакого способа возвратить результат в вызвавшую! Переданный параметр не изменяется в вызвавшей подпрограмме а только в вызванной. Ясно, что так работы не сделать.

Существуют два эквивалентных ответа на эту проблему. В Паскале Вирт предусмотрел параметры-переменные, которые передаются по ссылке. VAR параметр не что иное как наш старый друг параметр Фортрана с новым именем и расцветкой для маскировки. Вирт аккуратно обходит проблему «изменения литерала» так же как проблему «адрес выражения» с помощью простого средства, разрешая использовать в качестве фактических параметров только переменные. Другими словами, это тоже самое ограничение, которое накладывали самые ранние версии Фортрана.

Си делает ту же самую вещъ, но явно. В C все параметры передаются по значению. Однако одним из видов переменных, которые поддерживает С, является указатель. Так передавая указатель по значению, вы в действительности передаете то, на что он указывает по ссылке. В некоторых случаях это работает даже еще лучше, потому что даже хотя вы и можете изменить указываемую переменную на все, что хотите, вы все же не сможете изменить сам указатель. В функции типа strcpy, к примеру, где указатель увеличивается при копировании строки, мы в действительности увеличиваем только копии указателей, так что значение указателей в вызвавшей процедуре все еще остается каким было. Чтобы изменить указатель вы должны передавать указатель на указатель.

Так как мы просто проводим эксперименты, мы рассмотрим и передачу по значению и передачу по ссылке. Таким образом у нас будет возможность использовать любой из них как нам нужно. Стоит упомянуть, что было бы тяжело использовать здесь подход С, так как указатель это другой тип а типы мы еще не изучали!

Передача по значению

Давайте просто попробуем некоторые нехитрые вещи и посмотрим, куда они нас приведут. Давайте начнем со случая передачи по значению. Рассмотрим вызов процедуры:

FOO(X, Y)

Почти единственным приемлемым способом передачи данных является передача через стек ЦПУ. Поэтому, код который мы бы хотели видеть сгенерированным мог бы выглядеть так:

MOVE X(PC),-(SP) ; Push X

MOVE Y(PC),-(SP) ; Push Y

BSR FOO ; Call FOO

Это конечно не выглядит слишком сложным!

Когда BSR выполнен центральный процессор помещает адрес возврата в стек и переходит к FOO. В этой точке стек будет выглядеть следующим образом:

.

.

Значение X (2 bytes)

Поделиться:
Популярные книги

Седьмая жена короля

Шёпот Светлана
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Седьмая жена короля

Протокол "Наследник"

Лисина Александра
1. Гибрид
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Протокол Наследник

Нищенка в Королевской Академии магии. Зимняя практика 2

Майер Кристина
2. Нищенка а Академии
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Нищенка в Королевской Академии магии. Зимняя практика 2

Аргумент барона Бронина 3

Ковальчук Олег Валентинович
3. Аргумент барона Бронина
Фантастика:
попаданцы
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Аргумент барона Бронина 3

Измена. Осколки чувств

Верди Алиса
2. Измены
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Осколки чувств

Кто ты, моя королева

Островская Ольга
Любовные романы:
любовно-фантастические романы
7.67
рейтинг книги
Кто ты, моя королева

Родословная. Том 2

Ткачев Андрей Юрьевич
2. Линия крови
Фантастика:
городское фэнтези
аниме
фэнтези
5.00
рейтинг книги
Родословная. Том 2

Чехов. Книга 2

Гоблин (MeXXanik)
2. Адвокат Чехов
Фантастика:
фэнтези
альтернативная история
аниме
5.00
рейтинг книги
Чехов. Книга 2

Темный Лекарь 6

Токсик Саша
6. Темный Лекарь
Фантастика:
аниме
фэнтези
5.00
рейтинг книги
Темный Лекарь 6

Цикл "Идеальный мир для Лекаря". Компиляция. Книги 1-30

Сапфир Олег
Лекарь
Фантастика:
боевая фантастика
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Цикл Идеальный мир для Лекаря. Компиляция. Книги 1-30

Его нежеланная истинная

Кушкина Милена
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Его нежеланная истинная

Кодекс Крови. Книга III

Борзых М.
3. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга III

Идеальный мир для Лекаря 29

Сапфир Олег
29. Лекарь
Фантастика:
юмористическое фэнтези
аниме
фэнтези
5.00
рейтинг книги
Идеальный мир для Лекаря 29

Младший сын князя

Ткачев Андрей Сергеевич
1. Аналитик
Фантастика:
фэнтези
городское фэнтези
аниме
5.00
рейтинг книги
Младший сын князя