Передача по ссылке в Паскале - PullRequest
0 голосов
/ 09 февраля 2019

Я не уверен, правильно ли я понимаю, как работает передача по ссылке в Паскале.Создает ли он псевдоним, как в C ++ (https://isocpp.org/wiki/faq/references), или он работает аналогично C, и процедура получает указатель на переменную и использует этот указатель.

Полагаю, я мог бы сформулировать свой вопросas: Поддерживает ли Pascal истинную передачу по ссылке, или это делается по вызову путем совместного использования.

Например, ссылка FreePascal утверждает, что процедура получает указатель (https://www.freepascal.org/docs-html/current/ref/refsu65.html),, но согласно https://swinbrain.ict.swin.edu.au/wiki/Pass_by_Value_vs._Pass_by_Reference#Conclusion и, например, https://cgi.csc.liv.ac.uk/~frans/OldLectures/2CS45/paramPassing/paramPassing.html#callByReference передача по ссылке в Паскале работает иначе, чем в C (где передается указатель).

Если кто-то может объяснить немного больше о различиях или о том, как смыслпередача по ссылке изменилась (в современных языках мы называем передачу по ссылке, но на самом деле они передаются по значению, как, например, Java). Каково же первоначальное значение передачи по ссылке и как это работает? И как это происходит?тогда на Паскале?

Большое спасибо.

Ответы [ 2 ]

0 голосов
/ 09 февраля 2019

Более простой ответ, чем (очень хороший) другой.

работает ли он так же, как в C, и процедура получает указатель на переменную и использует этот указатель.

Да, это то, что происходит под капотом.Процедура действительно получает указатель, адрес, к переменной.Но компилятор, зная это, делает его прозрачным.Таким образом, внутри процедуры, которая объявляет параметр «a», оператор:

a := a div 2;

может быть скомпилирован двумя различными способами.Если параметр a объявлен нормально, т.е. передан по значению, оператор компилируется следующим образом:

1 - загрузить значение по адресу "a"
2 - целочисленное деление на два
3- сохранить результат по адресу "a"

Если вместо этого параметр был объявлен как var, то есть передан по ссылке, компилятор делает:

1 - загрузить значение по адресу"a"
2 - загрузить значение по только что загруженному адресу (это разыменование указателя)
3 - делить
4 - вернуть обратно

Выше четыре оператораэто именно то, что компилирует C, если источник:

*a = *a / 2;

Наверное, я мог бы сформулировать свой вопрос так: Поддерживает ли Паскаль истинную передачу по ссылке ...?

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

myproc(a);  // pascal and C are identical

Все становится иначеесли процедура ожидает передачи по ссылке:

myproc(a);  // pascal: identical to before

myproc(&a); // C: the language does not hide anything

Об этом последнем пункте кто-то думает, что C лучше, потому что это заставляет программиста знать, что переданная переменная может быть изменена процедурой (функцией).Вместо этого я думаю, что паскаль более элегантен, и что программист все равно должен знать, что будет делать процедура.

Все это для «простых» типов.Если мы говорим о строках (а у современного паскаля есть две разновидности), то же самое - в Паскале.Компилятор копирует, увеличивает количество ссылок и делает все необходимое для полной поддержки передачи по значению или по ссылке.В языке C нет ничего похожего.

Если говорить о классах, то все по-другому, но они должны все равно различаться из-за семантики классов.

Надеюсьдобавить что-то к другому полному ответу.

0 голосов
/ 09 февраля 2019

Передача по ссылке

в Delphi, передача по ссылке (используя var или out ) означает передачу указателя.Но обратите внимание, что существует разница между семантикой «передача по значению» или «передача по ссылке» и фактическим передачей.

var или out

Разница сC не фактическая передача (по указателю), а только то, что означают эти ключевые слова. Var просто проходит по ссылке. Out по-разному обрабатывает определенные управляемые типы, поскольку при out вы сообщаете компилятору, что входное значение не гарантируется для инициализации.В противном случае они технически совпадают (но не семантически): передается адрес (IOW, указатель на) исходных значений.

Семантика <> фактическая передача

Семантика

  • Семантика передачи по значению заключается в том, что подпрограмма получает локальную копию исходного значения , и что подпрограмма может (если это разрешено) изменить ее, не затрагиваяоригинал.Изменения применяются к локальной копии и исчезают, когда процедура заканчивается.
  • Семантика передачи по ссылке заключается в том, что вы обращаетесь (и, возможно, изменяете) к оригиналу .

Фактическая передача низкого уровня может отличаться

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

Поскольку у вас все еще есть локальная копия , и вы не изменяете оригинал, это все равно считается передачей по значению , как вы и заявили.Все технические вещи происходят прозрачно для пользователя, поэтому разница только на более низком уровне.Это имеет значение, только если вы пишете на ассемблере или должны читать сгенерированный код в окне ЦП.

Const

Если параметр значения объявлен const, оригинал все равно не изменяется, поэтому копированиебольшой структуры в локальный фрейм может быть опущен, и значения могут быть доступны (только для чтения) по ссылке (указатель), даже если семантика передать по значению .Маленькие значения всегда передаются по значению (в регистре или в стеке), в таких случаях.

Хотя не имеет смысла иметь const var в качестве модификатора параметра (что-то постоянное или переменное,но не оба), вы все равно можете форсировать передачу по ссылке параметра const, используя атрибут модификатора [ref]: const [ref] X: Integer или [ref] const X: Integer.Целое число обычно передается по значению (в регистре или в стеке, в зависимости от соглашения о вызовах и платформы).

Типы ссылок

Обратите внимание, что если вы передаете типы ссылок (например, объекты,динамические массивы и т. д.) по значению семантика передачи * по значению применяется только к самим ссылкам , т. е. вы получаете их копию и можете изменять ссылку без влияния на оригинал.

НО : элементы (объекты, массивы и т. Д.), На которые эти ссылки указывают , могут быть изменены .Только ссылки сами являются локальными копиями, а не на то, на что они указывают.Так что если вы вызываете метод для ссылки на объект, переданной по значению, этот объект (в куче) может быть изменен в конце концов!Это не потому, что передача по значению или передача как константа не работают должным образом, а из-за того, что ссылки.

Заключение

  • Передача по значению означает a копия оригинала изготовлена, и эта копия может быть изменена локально.
  • Передача по ссылке означает передается ссылка (указатель) на оригинал, и любая модификация изменяет оригинал .
  • Под капотом, технически , при передаче по семантике значения указатель можетпройти в конце концов.При необходимости создается копия оригинала, поэтому оригинал не изменяется в конце концов.
  • Передача ссылочных типов по значению или даже в виде const не означает исходные элементы (кучу)на что они указывают не могут быть изменены .Для предотвращения этого не существует C ++ - подобной const концепции.

Немного больше о ссылках и указателях можно найти в моей (очень популярной) статье Указатели адресации .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...