![]() |
1. Заголовок или название темы должно быть информативным !
2. Все тексты фрагментов программ должны помещаться в теги [code] ... [/code] или [code=pas] ... [/code].
3. Прежде чем задавать вопрос, см. "FAQ" и используйте ПОИСК !
4. НЕ используйте форум для личного общения!
5. Самое главное - это раздел теоретический, т.е. никаких задач и программ (за исключением небольших фрагментов) - для этого есть отдельный раздел!
![]() |
Neznaika |
![]()
Сообщение
#1
|
Пионер ![]() ![]() Группа: Пользователи Сообщений: 51 Пол: Мужской Репутация: ![]() ![]() ![]() |
Извиняюсь за возможное нарушение правил, но решил поместить пример программы,
чтобы сразу было понятно что к чему. ПРОГРАММА: Код program VarStr; uses Dos; procedure Proc( var Dir : DirStr; var Name : NameStr; var Ext : ExtStr ); begin end; procedure Proc2( var B : Byte; var W : Word; var L : LongInt ); begin end; procedure Proc3( var I : Integer; var W : Word ); begin end; procedure Proc21( B : Byte; W : Word; L : LongInt ); begin end; var SD, SN, SE : String; SDir : DirStr; SName : NameStr; SExt : ExtStr; B : Byte; W : Word; L : LongInt; I : Integer; begin (*Proc(SD,SN,SE); { НЕЛЬЗЯ! Ошибка 26: Type mismatch(несовпадение типов). }*) Proc(SDir,SName,SExt); { Всё в порядке! } (*Proc2(B,B{Error 26!},B);*) (*Proc2(W{Error 26!},W,W);*) (*Proc2(L{Error 26!},L,L);*) Proc2(B,W,L); { Всё в порядке! } (*Proc3(W{Error 26!},W);*) (*Proc3(W{Error 26!},I);*) (*Proc3(I,I{Error 26!});*) Proc3(I,W); { Всё в порядке! } Proc3(Integer(W),Word(I)); { Всё в порядке! } Proc21(B,W,L); { Всё в порядке! } Proc21(L,B,W); { Всё в порядке! } Proc21(W,L,B) { Всё в порядке! } end. И сам ВОПРОС(недеюсь он теоретический(имеет отношение к синтаксису, семантике и т.д. и т.п)): Почему типы фактических параметров переменных, задаваемых при вызове подпрограммы, должны СОВПАДАТЬ(быть РАВНЫМИ) соответствующим формальным VAR-параметрам. Почему здесь ошибка 26(Type mismatch) - НЕСООТВЕТСТВИЕ ТИПОВ превращается в ошибку НЕСОВПАДЕНИЕ ТИПОВ. Пожалуйста, если кто-нибудь знает, объясните. |
![]() ![]() |
hardcase |
![]()
Сообщение
#2
|
![]() code warrior ![]() ![]() ![]() ![]() Группа: Пользователи Сообщений: 484 Пол: Мужской Реальное имя: Славен Репутация: ![]() ![]() ![]() |
Есть такое понятие в программировании - безопасный код.
Помимо всего прочего (про exceptionы и потокобезопасность здесь речь не пойдет) оно включает в себя стиль написания программы, который не допускает работу с указателями в явной форме - получение, разыменование, арифметика на ним, также не приветствуются операции приведения типов. Вместо указателей настоятельно рекомендуется использовать ссылки, а типы преобразовывать в явном виде - через операции присваивания, встроенные функции и т.п. Т.е. нужно как можно больше работы сбрасывать на компилятор - статический контроль типов, управление памятью и прочую рутину. Он умеет это лучше чем человек. Теперь по поводу совместимости и эквивалентности. Совместимость типов - это такое отношение между двумя типами, которое доступно компилятору на этапе синтаксического анализа исходника. Т.е. компилятор ЗНАЕТ как перевести тип А в тип Б. Например real совместим с integer (переменной типа real можно присвоить значение переменной типа integer), но не наоборот. Эквивалентность типов - имеется в виду двоичная эквивалентность, это отношение между типами, выстроенное на основе размера памяти в байтах, который занимает переменная того или иного типа. Например у нас есть запись вида: Код TMyDWord = packed record HiWord: Word; LoWord: Word; end; Если мы имеем переменную типа Dword то мы вполне можем привести её к типу TMyDWord. Это приведение допустимо потому что размер занимаемый TMyDword равен размеру DWord. Обратное приведение также возможно. Эквивалентность типов может зависеть от настроек компилятора. Если мы поставим выравнивание полей записи по 4 байтам (это сильно ускорит их обработку) приведенный выше пример не будет работать, так как размеры перестанут совпадать и отношение двоичной эквивалентности между типами пропадет. Операция приведения типа оперирует с понятием эквивалентности типов. Мы можем привести тип А к типу Б в том случае, когда size(А) >= size(Б). Это ограничение не позволит обратиться к, возможно, невыделенной области памяти, что приведет к AV-исключению. При передаче параметров в подпрограммы или методы, для компилятора очень важен ТИП подставляемх фактических параметров, именно на основе их типов, он будет вызывать нужную перегруженную версию (если они есть) сабрутины. Отсюда правило - нужно ЗНАТЬ что ты хочешь сделать, чтобы небыло недопонимания с компилером. Цитата Мне кажется, что оба действия - и Type1(Type2Variable) и Type1((@Type2Variable)^) - выполняются на этапе Я уже объяснял..... Первый вариант приводит к копированию данных во временную переменную. Второй вариант компилятор рассматривает как некое переобъявление переменной. Разыменованный указатель - это переменная, операция приведения типа выступает в качестве декларирования типа переменной. Именно поэтому такая запись пригодна для передачи параметра по ссылке.компиляции. Но почему в первом случае создаётся локальная копия(для VAR-параметров), по какому синтаксическому правилу? Добавлено через 6 мин. Ваял предыдущий креатив..... А можно ли вообще использовать в качестве фактических параметров процедур для VAR-параметров ВЫРАЖЕНИЯ? Для W типа Word конструкция Byte(W) - это выражение. В принципе - можно. Если выражение своим результатом возвращает указатель, то используя технику дзен Код Type1((PType1PointerExpression)^) Мы можем передавать данные по ссылке. Другое дело, что нам потребуется написать выражение, результатом которого будет некий указаталь (с точки зрения безопасного кода подобные действия никуда не годятся). -------------------- ИзВ ин ИтЕ зА нЕ рОв НЫй П оч ЕРк
|
![]() ![]() |
![]() |
Текстовая версия | 24.06.2025 7:27 |