$AppType — Директива компилятора Delphi


Список директив компилятора Delphi, нужно ли указывать директивы перед именем устройства?

im работает над приложением, используя delphi 7, и я просто наткнулся на это

автор кода разместил так много директив компилятора перед именем основного устройства.

может кто-нибудь сказать мне

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

Что касается того, влияет ли директива на весь проект, целый блок, одна функция и область с функцией, которая варьируется от директивы к директиве. Вы должны прочитать документацию для каждой директивы, чтобы узнать, какова ее область действия.

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

Директивы переключателей являются глобальными или локальными:

  • Глобальные директивы влияют на всю компиляцию и должны отображаться перед объявлением части программы или скомпилированного устройства.
  • Локальные директивы влияют только на часть компиляции, которая простирается от директивы до следующего появления той же директивы. Они могут появляться где угодно.

Однако рассмотрите директиву DENYPACKAGEUNIT (внимание мое):

Директива <$DENYPACKAGEUNIT ON>предотвращает создание блока Delphi, из которого он помещается в пакет.

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

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

Обратите внимание, что вам нужно всего лишь установить директивы в коде, если вы хотите изменить настройки по сравнению с настройками проекта. Разумно установить параметры в параметрах проекта и не устанавливать их в коде.

То, что, по-видимому, произошло в представленном вами коде, заключается в том, что автор набрал CTRL+O O , а среда IDE вставила различные параметры, определенные в параметрах проекта в этот момент времени.

Директивы компилятора для Debug/Release

14.11.2020, 20:14

Директивы компилятора
Ребят знает кто как отключить ошибки такого рода(см.ниже) Она выскакивает если оставить.

Различия между Debug и Release
Чем отличаются Debug и Release версии файла, кроме размера самого файла на выходе? Я так понял они.

В чем отличие Debug от Release
Народ, конкретно чем отличается дебаг от релиза. Я новичок совсем, поэтому не шарю. Но компилируя в.

Почему Release и Debug работают по разному
Уже не в первый раз происходит так, что откомпилированный в режиме Release проект работает не так.

Почему некоторые методы в Release не работают, тогда как в Debug все нормально?
Всем привет! Пришло время узнать, а собственно почему некоторые методы в Reliase не работают, так.

Директивы по версиям компилятора Delphi: <$ IFDEF VER180>— 2020

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

Если вы планируете писать код Delphi, который должен работать с несколькими версиями компилятора Delphi, вам необходимо знать, в каких версиях компилируется ваш код.

Предположим, вы пишете свой собственный (коммерческий) пользовательский компонент. Пользователи вашего компонента могут иметь разные версии Delphi, чем у вас.

Если они попытаются перекомпилировать код компонента (ваш код) — у них могут быть проблемы! Что если вы использовали параметры по умолчанию в ваших функциях, а у пользователя Delphi 3?

Директива компилятора: $ IfDef

Директивы компилятора — это специальные синтаксические комментарии, которые мы можем использовать для управления функциями компилятора Delphi. Компилятор Delphi имеет три типа директив: переключение директив, директивы параметров а также условные директивы, Условная компиляция позволяет нам выборочно компилировать части исходного кода в зависимости от того, какие условия установлены.

Директива компилятора $ IfDef запускает секцию условной компиляции.

Синтаксис выглядит так:

DefName представляет так называемый условный символ. Delphi определяет несколько стандартных условных символов. В приведенном выше «коде», если определено DefName, код выше $ Else компилируется.

Delphi Version Symbols

Распространенным применением директивы $ IfDef является тестирование версии компилятора Delphi.

В следующем списке указаны символы, которые необходимо проверить при условной компиляции для конкретной версии компилятора Delphi:

  • УСЛОВНОЕ ОБОЗНАЧЕНИЕ — Компиляционная версия
  • VER80 — Delphi 1
  • VER90 — Delphi 2
  • VER100 — Delphi 3
  • VER120 — Delphi 4
  • VER130 — Delphi 5
  • VER140 — Delphi 6
  • VER150 — Delphi 7
  • VER160 — Delphi 8
  • VER170 — Delphi 2005
  • VER180 — Delphi 2006
  • VER180 — Delphi 2007
  • VER185 — Delphi 2007
  • VER200 — Delphi 2009
  • VER210 — Delphi 2010
  • VER220 — Delphi XE
  • VER230 — Delphi XE2
  • WIN32 — Указывает, что операционной средой является Win32 API.
  • LINUX — Указывает, что операционной средой является Linux
  • MSWindows — Указывает, что операционной средой является MS Windows / li]
  • ПРИСТАВКА — Указывает, что приложение компилируется как консольное приложение.

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

Примечание: символ VER185, например, используется для обозначения компилятора Delphi 2007 или более ранней версии.


Использование символов «VER»

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

Например, функция IncludeTrailingBackslash, представленная в Delphi 5, добавляет «» в конец строки, если ее там еще нет. В проекте Delphi MP3 я использовал эту функцию, и несколько читателей пожаловались, что не могут скомпилировать проект — у них есть какая-то версия Delphi до Delphi 5.

Одним из способов решения этой проблемы является создание собственной версии этой подпрограммы — функции AddLastBackSlash.

Если проект должен быть скомпилирован на Delphi 5, вызывается IncludeTrailingBackslash. Если используются некоторые из предыдущих версий Delphi, мы моделируем функцию IncludeTrailingBackslash.

Это может выглядеть примерно так:

функция AddLastBackSlash (ул: строка) : строка; начать Результат: = IncludeTrailingBackslash (str); если Copy (str, Length (str), 1) = «» затем Результат: = ул еще Результат: = str + «»; конец;

При вызове функции AddLastBackSlash Delphi выясняет, какая часть функции должна использоваться, а другая часть просто пропускается.

Delphi 2008?

Delphi 2007 использует VER180 для обеспечения неразрывной совместимости с Delphi 2006, а затем добавляет VER185 для разработки, которая по каким-либо причинам должна быть нацелена на Delphi 2007.

Примечание. Каждый раз, когда интерфейс модуля изменяет код, использующий этот модуль, его необходимо перекомпилировать.Delphi 2007 — выпуск без прерываний, означающий, что файлы DCU из Delphi 2006 будут работать как есть.

$AppType — Директива компилятора Delphi

цитата: Artemiy
Проверил.
Версия CodeGear™ Delphi® 2007 for Win32® Version 11.0.2902.10471
1. не подтверждается, все работает логично.

Вчера весь вечер мучался, сегодня проблема не воспроизводится, чудеса в решете

404. Bilchenko , 12.03.2008 15:14
Гуру помогите, что значит «If shutdown is from another Init section», а то очень хочется включить IDFREEONFINAL, а фраза только пугает.

405. Anthony DE , 19.03.2008 05:00
По поводу билдеров. Я начинал с первого C++ Builder, потом долго работал на третьем.

Недавно понадобилось кое что сваять с использованием стороннего COM-компонента в виде TLB-DLL (не контрол!). С com-ом я раньше вообще не работал.

Ну само собой, решил взять свежайший C++ Builder, чтобы без лишней головной боли сделать то, что нужно.

Люди! Это ппц какой-то! Попробовал CodeGear C++ Builder 2007, потом BDS-2006. Это просто ужас какой-то! Среды жутко глючные, то что мне надо, я там припинать не смог.

Взял C++ Builder 6 и обрел счастье!

Так вот касательно именно билдера — что там в новых версиях реально нового и полезного по сравнению с C++ Builder 6, кроме закоса интерфейса под MS и дурацкого HTML-хелпа с отсутствием вменяемых примеров?

P.S. HTML-хелп — песня особая. Когда писал на MSVC, всегда ставил дистрибутив с хелпами от третьего билдера, т.к. там для WinAPI, да и по самому языку C/C++ гораздо более вменяемая информация и удобнее для использования. Конечно, в HTML-хелп тоже приходилось лазить, в случае отсутствия нужного в старом хелпе

цитата: Bzzz:
С# и .Net в своей основе является миксом из Java и Delphi, что решает многие проблемы с идеологией и основными библиотеками. Отличия есть, но новой технологией это не назвать.
Большее количество заимствований все-таки из Жабы. Так сказать «работа над ошибками», и надо заметить, хорошо продуманная работа (в значительной степени речь идет о .NET в целом, чем о C# в частности).
А о том, что с C# в ближайшем будующем прийдется переучиваться — маловероятно. Количество тех, кто пишет под Windows на C#/VB под .NET будет неуклонно расти, вытесняя динозавров, юзающих C++ (в связке с какой-нить поделкой вроде MFC). Принциально новый API грядущего Windows представляет собой библиотеку .NET классов, свободно юзаемую из любого .NET языка (включая тот же Delphi.NET).
На откуп C++ останется относительно небольшая сфера приложений критичных к производительности (скорее всего это будут dll, вызываемые из managed кода) и драйверов.
(с)

Посмотрел Win2008- сплошной нативный С++. .Net — как был так и есть и думаю так и останется прослойкой для самопальных приложений.
Сам-то мотор .NET на чем написан ?

406. Balin , 19.03.2008 06:50

цитата: Adalon:
Сталкнулся с такой проблемой.
После перехода с C++Builder 6 на BDS2006 сам не обнаружил эту фишку.
Но когда пользователи программы сообщили — посмотрел и убедился.
При нажатии F1, т.е. вызове контекстной помощи, программа выдает сообщение
«No Context-sensitive help installed».
По помощи я ничего не менял.
HLP-файл создан еще утилиткой поставляемой вместе с C++Builder6.

Как буд-то файла просто нет. Или он другого формата.
В чем проблема?

Uses WinHelpViewer;

407. copyprof , 13.05.2008 09:40
408. redshadow , 20.05.2008 23:01
Кто нибудь делал для трея отображение всплывающего окна как у касперского
409. PrintF , 30.06.2008 03:08
подскажите плиз.

1) чем DelphiSpeedUp IDE plugin хуже/лучше/надежней чем CnWizards (их модуль оптимайз фаст_коде)
2) в чём могут быть грабли при использовании DelphiSpeedUp
3) кто нить юзает такую штуку — Bcc32Pch IDE Plugin? в чём могут быть грабли сего продукта?
4) кто нить пользуется TwineCompiler 2.0.12?

Добавление от 30.06.2008 03:16:

5) кто нить пробовал использовать в своих проектах такой файл — RtlVclOptimize.pas ?

410. Artemiy , 30.06.2008 08:50
Использую DelphiSpeedUp IDE plugin и RtlVclOptimize.pas, глюков не замечено.
411. PrintF , 30.06.2008 15:30
а вот RtlVclOptimize.pas, реально ускоряет выполнения собственных приложений?

попробовал такой код. с RtlVclOptimize.pas и без. особой разницы не заметил, даже на 10 мс вроде как стало медленнее.

и еще.
RtlVclOptimize.pas просто включить в проект через Add Project и перекомпилировать проект, и всё?

412. Alexzzy , 04.10.2008 14:07
Ха, у Дельфи опять новый владелец.

SAN FRANCISCO — July 1, 2008 — Embarcadero Technologies, a privately-held company of Thoma Cressey Bravo, completed the acquisition of CodeGear from Borland Software Corporation (NASDAQ: BORL) for approximately $24.5 million on June 30. CodeGear is being integrated into Embarcadero Technologies, which will continue to operate as a private company under the leadership of current Embarcadero CEO Wayne Williams.

Для тех кто не знает, Embarcadero специализируется на, так сказать, инфрастуктурных продуктах для СУБД.
Пользуюсь ихним DBArtisan — функционал хороший, но исполнение не очень. Вот и в придачу к Delphi 2009 Architect свою лабуду для СУБД запихнули.
Незнаю прям, хорошо все это или плохо.

413. A6WideUser , 04.10.2008 14:43
Alexzzy

Вышел из спячки . Об этом известно стало очень давно, ажно в первых числая мая сего года )

Незнаю прям, хорошо все это или плохо.

Скорее хорошо, иначе загнулся бы хороший инструмент вместе с Борландом. Еще положительный момент в том, что в Embarcadero работают люди стоявшие «у истоков» Delphi, т.е. разработчики принимавшие участие в разработке (каламбурс) еще Борландовой Delphi. Еще хорошо, что взгляды их устремлены не тупо на Win+.Net, а еще и на Linux и MacOS (это в блогах кто-то из Embarcadero писал). Ну и, наконец, положительная динамика уже просматривается в Delphi 2009, как в среде так и в языке.

414. Alexzzy , 04.10.2008 15:25
A6WideUser
Вышел из спячки . Об этом известно стало очень давно, ажно в первых числая мая сего года
Вышел. Я просто не слежу постоянно за Delphi, а тут вроде как не проскакивало. А тут заглянул на CodeGear и тут тебе на.

Ну и, наконец, положительная динамика уже просматривается в Delphi 2009, как в среде так и в языке.
Не рановато ли просматривается, может это пока еще чисто наработки CodeGear?

Ну будем надеяться что это к лучшему.
Кстати, помнится когда Delphi 2007 еще не было, в планах на Delphi 2008 было упомянута разработка компонентов (технологии) для «прозрачной» замены BDE, ну типа что бы можно было убрать BDE без переписывания кода. Вот этого чёта пока не видно, а для меня это еще актуально. Возможно и похерили.

415. A6WideUser , 04.10.2008 15:52
Alexzzy

Ну и, наконец, положительная динамика уже просматривается в Delphi 2009, как в среде так и в языке.
Не рановато ли просматривается, может это пока еще чисто наработки CodeGear?

Так, вероятно, и есть, мне вообще не кажется, что Embarcadero что-то привнесет именно в Delphi, они же не разработкой языков занимаются. Но с другой стороны, где CodeGear себя чувствует лучше, под крышей частной компании (весьма заинтересованной в развитии Delphi) или акционерной, где прямой конкурент имеет влияние? Это много значит, мне кажется Хотя, CodeGear и сами по себе молодцы, D2007 отличная работа над ошибками всех версий начиная с 8

Кстати, помнится года два назад, когда Delphi 2007 еще не было, в планах на Delphi 2008 было упомянута разработка компонентов (технологии) для «прозрачной» замены BDE, ну типа что бы можно было убрать BDE без переписывания кода. Вот этого чёта пока не видно, а для меня это еще актуально. Возможно и похерили.

Возможно и будет, позже Просто им сейчас нужен был релиз, и релиз непровальный. Они же и так проделали огромную работу — все под юникод перевели, дженерики опять же На все времени просто не хватило. Бауэр недавно в блоге сокрушался, что хотели внести в язык что-то типа managed records, (записи имеющие конструктор и деструктор отрабатывающие в момент входа/выхода в/из зоны видимости) но тоже не успели. Я вот с D2006 жду, когда добавят перегрузку оператора присваивания, может и дождусь как нибудь (различия в implicit/explicit дождался уже )

416. продукт распада , 20.05.2009 11:21
пришлось тут немного в делфи писать, есть вопрос, не принципиальный, т.к. можно обойти, но при выполнении получается что-то непонятное.
Есть массив, в конкретном случае его нужно заполнить нулями.

a: array of double;

SetLength(a, asize);
FillChar(a, sizeof(a), 0);

В общем, это не работает, я сначала хотел спросить, почему, но вроде понял, что дело в том, что массив динамический, а так можно поступать только со статическим массивом. Неужели перебором?
Вообще, в отладчике видно, что массив заполнен нулями в начале, в принципе, этого было бы достаточно, но только тут вопрос: есть ли гарантия, что массив обязательно инициализируется нулями?

417. Джамаль , 20.05.2009 11:37
продукт распада


Нет, гарантии нету — оно не инициализируется, там после создания мусор. Заполнять его нужно, действительно, перебором

for cnt := 0 to High(a) do a[cnt]:=0;

Добавление от 20.05.2009 11:42:

Кстати, в случае с динамическими массивами sizeof не прокатывает — нужно использовать length или High. Причина всё та же — для процессора динамический массив суть всего лишь указатель на кусок памяти, распределяемый динамически, а не на предварительно выделенную область перед стеком, размер которой известен уже во время сборки.

418. W2k_fan , 20.05.2009 11:49
продукт распада
419. A6WideUser , 20.05.2009 14:22
продукт распада
есть ли гарантия, что массив обязательно инициализируется нулями?

Есть. Читаем хелп. Смотрим на процедуру DynArraySetLength в System.pas.

Но вообще можно и ручками, если требуется: FillChar(Pointer(DynArray)^, Length(DynArray) * SizeOf(DynArrayItem), 0);

420. Джамаль , 20.05.2009 14:55
A6WideUser

Что-то у меня порой динамический массив с мусором оказывался сразу после создания.

421. A6WideUser , 20.05.2009 15:05
Джамаль
Что-то у меня порой динамический массив с мусором оказывался сразу после создания.

Это фантастика. Или сайд-эффект кривого кода. Дин. массивы инициализируются нулевыми значениями с момента своего появления в Delphi 4.

422. Джамаль , 20.05.2009 15:07
Жаль, что со справкой у меня проблемы Может, просто посмотрел не туда при отладке.
423. istomin , 20.05.2009 15:19
SetLength(a, asize);
FillChar(a, sizeof(a), 0);

FillChar(a[0], length(a)*sizeof(a[0]), 0);
424. A6WideUser , 20.05.2009 15:25
istomin

Заменить на Pointer(a)^, да и SizeOf(a) тоже менять нужно на Length(a) * SizeOf(a[0]);

Условная компиляция в Delphi

Условная компиляция в Delphi, по сути, очень полезная и удобная возможность, которая позволяет Delphi компилировать или не компилировать код в зависимости от определенных символов условной компиляции. Говоря более простым языком (возможно и не совсем корректно), условная компиляция позволяет убрать или, наоборот, добавить часть кода исполняемого файла. Так или иначе, любой Delphi разработчик встречается с символами условной компиляции как минимум один раз за время работы над проектом.

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

Для начала, рассмотрим очень простой код, который вы можете повторить в Delphi за несколько секунд:

Теперь нажмите F9 и проверьте, что написано в отладчике в «Events»:

Разберемся с тем, что мы только что написали.

$IFDEF — это директива компилятора;

DEBUG — условное определение или символ условной компиляции. Символ обязательно должен начинаться с буквы за которой может следовать любое количество букв, цифр и знаков подчеркивания, однако использоваться будут лишь первые 255 символов.

Процедура отправляет строку в отладчик для отображения.

Завершает условную компиляцию, инициированную последней директивой <$IFxxx>(почему не <$IFDEF>— смотрим далее).

Таким образом, используя директивы и мы указали компилятору дословно следующее: если где-либо по ходу компиляции был встречено условное определение DEBUG, то надо выполнить OutputDebugString.

Где определено условное определение DEBUG? Конкретно в этом случае, символ DEBUG можно найти, если зайти в настройки проекта: Project -> Options ->Delphi Compiler :

Здесь же можно определить и свои собственные символы. Давайте, например, добавим свой символ условной компиляции TEST. Для этого открываем диалоговое окно редактирования символов условной компиляции (жмем кнопку «…» в строке «Conditional defines») и заносим наш символ в список:

Теперь изменим наш код, приведенный в начале статьи, чтобы он работал с нашим символом условной компиляции:

Теперь можете снова запустить приложения в режиме отладки и посмотреть, что в Events появится строка «TEST IS ON».

Сейчас мы с вами рассмотрели самый простой способ использования условной компиляции в Delphi — использование директив и , а также определение собственного символа условной компиляции через свойства проекта. Вместе с этим, определить (включить) свой символ условной компиляции можно и в коде программы. Для этого используется директива компилятора . Воспользуемся этой директивой:

Соответственно, если есть директива определения нового символа, то должна быть и директива, которая отключает символы условной компиляции — она называется . Можете написать, например, вот такой код:

и убедиться, что символ DEBUG выключен, а в окне Events не появится строка «debug is on».

Двигаемся далее. Что делать, если нам необходимо вывести строку не когда символ включен, а именно тогда, когда он выключен? Здесь, опять же, есть варианты. Короткий вариант — воспользоваться директивой противоположной — она называется и код между и выполняется, если символ выключен:

Второй вариант — использование директивы , если в зависимости от состояния символа условной компиляции вам надо выполнять различные участки кода:

Соответственно, нет необходимости далее повторять этот же участок кода с использованием — работать будет, но прямо противоположно.

Также следует обратить внимание на то, что все условные символы оцениваются в Delphi, когда вы выполняете Build проекта. Справка Delphi рекомендует для надежности пользоваться командой Project -> Build All Projects, чтобы быть уверенным, что все символы условной компиляции определены верно.

В Delphi также определен набор символов условной компиляции, которые вы можете использовать при работе над своим проектом.

Например, символ условной компиляции VER330 определен для Delphi 10.3 Rio и с его помощью можно определить какой код должен или не должен выполняться, в случае, если версия компилятора Delphi — 33. Например, воспользуемся фичей Delphi 10.3 Rio под названием Inline Variable Declaration:

Сразу может возникнуть вопрос: как сделать так, чтобы приведенный выше код сработал не только в Delphi 10.3 Rio, но и в последующих версиях?
Это можно сделать воспользовавшись, например, такой конструкцией:

Здесь мы уже воспользовались директивой с помощью которой проверили значение константы CompilerVersion, которая находится в модуле System.

Здесь же стоит обратить внимание и на окончание блока — мы использовали директиву , как того требовала Delphi до версии Delphi XE4:

  • для директивы $IFDEF должна быть определена директива $ENDIF
  • для директивы $IF должна быть определена директива $IFEND

В XE4 нам разрешили использовать для закрытия блоков <$IF>, и . Однако, если у вас возникают проблемы при использовании связки и , то вы можете использовать специальную директиву , чтобы потребовать использовать для именно <$IFEND>:

Теперь, если в коде выше использовать директиву $ENDIF, то получим сообщение об ошибке:

Директиву , кстати, можно использовать и с другими константами проекта, например, так:

Так как наша константа Version содержит значение 2, то выполнится участок кода расположенный после . Можете сменить значение константы Version на 1, чтобы убедиться, что выполнится участок кода, где определена переменная s.

Как я сказал выше, в Delphi есть целый набор предопределенных символов условной компиляции. Ознакомиться со всеми этими символами вы можете на этой странице справки по Delphi.

  1. Использование условной компиляции позволяет нам выполнять тот или иной код, в зависимости от того, какие константы и символы условной компиляции определены или не определены в проекте.
  2. Используя предопредленные символы условной компиляции можно указывать Delphi какой код необходимо выполнить, например, если программа собирается под Android, или, если поддерживается архитектура x64 и т.д.
  3. Директива $IF может использоваться с различными константами, в том числе и определенными самим разработчиком.

При подготовке статьи использовалась следующая информация официальной справки по Delphi:

$AppType — Директива компилятора Delphi

Группа: Пользователи
Сообщений: 4 825
Пол: Мужской
Реальное имя: Олег

Директивы компилятора
Почему-то мало кто пользуется директивами компилятора в полном масштабе.
Еще <$M> <$N> <$E>приходится видеть, но вот такие:
<$ifdef>. <$else>. — почти никогда; несмотря на то, что они открывают довольно широкие возможности для программиста, а именно: позволяют писать код, успешно компилируемый на разных компиляторах Паскаля, в том числе и 32 битных, включая FPC и TMT.

Еще одно удобство на мой взгяд — широкие возможности при отладке приложений.


Общий синтаксис этих команд таков:
— установить условный_символ.
— код следующий после этой директивы компилируется только в том случае, если условный_символ был установлен.
— эта директива обозначает начало альтернативного участка кода.
— ограничивает действие директив <$ifdef>и <$else>.

Режимы компиляции. Отладка.
Предположим, что в программе необходимо на этапе отладки выводить какие-то данные для тестирования алгоритма. Можно, конечно, в окончательном варианте кода закомментировать такие отладочные выводы, или удалить, но лучше заключить «отладочные операторы» в такую конструкцию, с использованием директив:

Таким образом, при работе программы на экран будет выведено значение «2». Если отладку надо отменить, мы можем убрать символ «$» из директивы <$define debug>— и теперь это будет просто коментарий, и следовательно на экран ничего не будет выведено.

Универсальность кода
Хорошо, когда мы берем старый код из TP и он компилируется, и программа правильно работает в компиляторе постарше.
А почему бы не реализовать совместимость наоборот или напрямую? Часто при компиляции, возникают ошибки только из-за того, что код оптимизирован под конкретный компилятор, например под BP, и в TP отказывается компилироваться.
Выходом из такой ситуации является правильное написание кода, а именно отладка кода под различные компиляторы (конечно если это требуется). Для примера рассмотрим программу для построения графиков некоторых функций (в полярной системе координат) скачать архив

Этот код можно скомпилировать вот в этих компиляторах: FPC(target: Win32, DOS), TP7, BP7, BPW (target:real, protected mode), TMT.
Неплохо, правда? И везде он будет работать одинаково правильно!
Конечно при компиляции в FPC под Win32, это будет windows приложение, а в остальных случаях консольное DOS (16 битное) приложение.
Прокоментирую первые строчки программы (а дальше я думаю все понятно)

Эмуляция сопроцессора
Очень часто у многих возникает вопрос — почему при компиляции у меня возникает ошибка Error 116: Must be in 8087 mode to compile this.
Ответ: Вы используете один из следующих вещественных типов:
Single, Double, Extended, Comp
Для работы с этими типами, необходима эмуляция сопроцессора. Просто добавьте в начало программы директивы:

Оптимизация
Для уменьшения размера программ желательно добавить следующие директивы:
<$B->— быстрое вычисление логических условий;

Но с оптимизацией будьте очень осторожны !! Например, вот такой пример будет компилироваться, но выдаст неверный результат (попробуйте запустить программу без ключей <$B->и <$B+>. ):

var x, y: integer;

begin
x := 2;
<$B->
if (x > 5) and do_it then y := x
else y := 2 * x;

<$D->— отключить информацию для отладки ­(пропадает возможность отлаживать программу. (через F7)­). При этом размер сократится на 100-150 байт.

Описание других директив

<$N+>— сопроцессор
<$E+>— эмуляция сопроцессора
<$I->— отключение проверок ввода/вывода
<$R->— отключение проверок на границы массивов
<$S->— отмена проверки на переполнение стека
<$Q->— отмена проверок на границы типов ­(overflow, underflow)

Директивы компилятора (продолжение)

Директивы без параметров:

  • Выравнивание данных . (Глобальная директива). Эта директива позволяет переключаться между выравниванием переменных и типизированных констант по границе слова (состояние <А+>) и по границе байта (состояние ). При выравнивании на границу слова адресация происходит за 1 цикл обращения к памяти вместо двух.
  • Эмуляция математического сопроцессора . (Глобальная директива). Разрешает (<$E+>) или запрещает (<$E->) компоновку с библиотекой, которая будет эмулировать работу сопроцессора в случае его отсутствия. При компиляции в режиме <$N+, E+>Паскаль выполняет компоновку с полным эмулятором сопроцессора. Полученный EXE файл может выполняться на любой машине независимо от присутствия сопроцессора.
    В состоянии <$N+, E->компоновка осуществляется с гораздо меньшей по размеру библиотекой, которая может использоваться только при наличии сопроцессора. (Эта директива не производит никаких действий при использовании ее в модуле. Она действует только при компоновке программы)
  • Выбор модели вызова (Far/Near) . (Локальная директива). Управляет выбором типа вызова компилируемых процедур и функций.

    В процессоре поддерживается два типа вызовов и инструкций возврата управления — ближние (NEAR) и дальние (FAR). Ближние вызовы передают управление другой ячейке в пределах того же программного сегмента, а дальние вызовы позволяют перейти в другой программный сегмент.

Инструкция ближнего обращения CALL помещает в стек 16-битовый адрес возврата (только смещение), а инструкция дальнего вызова помещает в стек 32-битовый адрес возврата (адрес сегмента и смещение). Соответствующая инструкция RET извлекает из стека только смещение или адрес сегмента и смещение.

При компиляции в режиме <$F+>все процедуры и функции всегда используют дальнюю модель вызова (Far Call). При указании директивы <$F->компилятор Паскаля автоматически выбирает необходимый тип обращений: дальний, если процедура или функция описывается в интерфейсном разделе модуля (с расчетом на вызов из других блоков), и ближний в случае описания в разделе Implementation.
Существует несколько случаев, когда требуется использовать директиву <$F+>. Например, при использовании оверлейных модулей и при передаче процедур/функций в качестве параметров они должны быть откомпилированы с расчетом на дальнюю модель вызова.

  • Режим контроля ввода/вывода . (Локальная директива). Этот ключ задает (<$I+>) или отменяет (<$I->) генерацию кода, проверяющего результат выполнения операций ввода/вывода. Если операция ввода/вывода не может завершиться корректно и включен режим <$I+>, происходит ошибка времени выполнения (Run-time Error). При отключенном контроле (режим <$I->) аварийного останова программы не происходит, и результат операции может быть проанализирован с помощью функции IOResult.
    Внимание: после первого обращения к IOResult, флаг ошибки сбрасывается, и проанализировать ошибку во второй раз не получится. Чтобы это сделать, нужно сохранить значение IOResult в какой-либо переменной, и проверять именно значение этой переменной .
  • Использование сопроцессора . (Глобальная директива). При указании режима <$N->генерируется код для программного выполнения всех вещественных вычислений. При режиме <$N+>генерируется код для выполнения таких вычислений аппаратно с помощью сопроцессора.
  • Режим проверки границ . (Локальная директива). Приводит в действие (<$R+>) или отменяет (<$R->) генерирование кода проверки границ. При указании <$R+>все выражения со строками и массивы проверяются на нахождение индекса в допустимых пределах (все операторы присваивания переменным скалярных типов проверяются на принадлежность границам типа). При нарушении диапазона происходит ошибка времени исполнения. Эта директива увеличивает размер программы и уменьшает скорость ее исполнения. Поэтому желательно использовать режим <$R+>при отладке, выключая его в окончательной версии.
  • Режим проверки переполнения стека . (Локальная директива). Приводит в действие (<$S+>) или отменяет (<$S->) генерирование кода проверки границ. При указании <$S+>генерируется код, проверяющий, достаточно ли места в стеке выделено для локальных переменных. При недостатке места в стеке происходит ошибка времени исполнения. В режиме <$S->наиболее вероятно произойдет «зависание» системы.
  • Режим проверки параметров строкового типа . (Локальная директива). В состоянии <$V+>выполняется строгая проверка типа, прикоторой требуется, чтобы формальный и фактический параметр имели иденимчные строковые типы. В состоянии <$V->ф качастве фактического параметра допускается использовать любую переменную строкового типа, даже если ее описанная длинна не совпадает с длиной соответствующего формального параметра.
  • Директивы с параметрами:

    • Компоновка файла объектных кодов . Данная директива предписывает компилятору скомпоновать указанный файл с компилируемой программой или модулем. Директива <$L имя_файла>используется для компоновки кода, написанного на ассемблере.

    Кроме линковки с OBJ файлами данная директива очень часто используется для включения BGI драйверов и шрифтов в EXE файл (для полностью автономной работы программы). Для того чтобы произвести эту операцию нужно сделать следующее:

    1. С помощью утилиты BINOBJ.EXE (входящей в дистрибутив Турбо Паскаля) преобразовать BGI файл в OBJ-формат (работа с утилитой BINOBJ осуществляется из командной строки):

    2. Подключить полученный OBJ файл к программе:

    Сама инициализация графики (например, режима VGA) будет осуществляться так:

    $AppType — Директива компилятора Delphi

    Как сделать свои собственные сообщения при компилляции

    Как узнать версию компиллятора ?

    Какие есть директивы компилятора?

    <$I+>и <$I->— директивы контроля ввода/вывода
    <$M>и <$S>— директивы, определяющие размер стека

    <$M+>и <$M->— директивы информации времени выполнения о типах
    <$Q+>и <$Q->— директивы проверки переполнения целочисленных операций

    <$R>— директива связывания ресурсов

    <$R+>и <$R->— директивы проверки диапазона

    <$APPTYPE CONSOLE>— директива создания консольного приложения

    1) Директивы компилятора, разрешающие или запрещающие проверку утверждений.

    По умолчанию <$C+>или <$ASSERTIONS ON>
    Область действия локальная

    Директивы компилятора $C разрешают или запрещают проверку утверждений. Они влияют на работу процедуры Assert,используемой при отладке программ. По умолчанию действует
    директива <$C+>и процедура Assert генерирует исключение EAssertionFailed , если проверяемое утверждение ложно.
    Так как эти проверки используются только в процессе отладки программы, то перед ее окончательной компиляцией следует указать директиву <$C->. При этом работа процедур Assert будет блокировано и генерация исключений EassertionFailed производиться не будет.
    Директивы действуют на весь файл исходного кода независимо от того, в каком месте файла они расположены.

    2) Директивы компилятора, включающие и выключающие контроль файлового ввода-вывода.

    По умолчанию <$I+>или <$IOCHECKS ON>
    Область действия локальная

    Директивы компилятора $I включают или выключают автоматический контроль результата вызова процедур ввода-вывода Object Pascal . Если действует директива <$I+>, то при возвращении процедурой ввода-вывода ненулевого значения генерируется исключение EInOutError и в его свойство errorcode заносится код ошибки. Таким образом, при действующей директиве <$I+>операции ввода-вывода располагаются в блоке try . except , имеющем обработчик исключения EInOutError . Если такого блока нет, то обработка производится методом TApplication.HandleException .
    Если действует директива <$I->, то исключение не генерируется. В этом случае проверить, была ли ошибка, или ее не было, можно, обратившись к функции IOResult . Эта функция очищает ошибку и возвращает ее код, который затем можно анализировать. Типичное применение директивы <$I->и функции IOResult демонстрирует следующий пример:

    AssignFile ( F,s );
    Rewrite (F);

    <$I+>
    i:=IOResult ;
    if i <> 0 then
    case i of
    2 : .
    3 : .
    end ;

    В этом примере на время открытия файла отключается проверка ошибок ввода вывода, затем она опять включается, переменной i присваивается значение, возвращаемое функцией IOResult и, если это значение не равно нулю (есть ошибка), то предпринимаются какие-то действия в зависимости от кода ошибки. Подобный стиль программирования был типичен до введения в Object Pascal механизма обработки исключений. Однако сейчас, по-видимому, подобный стиль устарел и применение директив $I потеряло былое значение.

    3) Директивы компилятора, определяющие размер стека

    По умолчанию <$M 16384,1048576>
    Область действия глобальная

    Локальные переменные в процедурах и функциях размещаются в стеке приложения. При каждом вызове процедуры или функции ее локальные переменные помещаются в стек. При выходе из процедуры или функции эти локальные процедуры удаляются из стека.
    Директивы компилятора $M задают параметры стека приложения: его минимальный и максимальный размеры. Приложение всегда гарантировано имеет размер стека, равный его минимальной величине. Если при запуске приложения Windows обнаруживает, что не может выделить этот минимальный объем памяти, то выдается сообщение об этой ошибке.
    Если во время работы выясняется, что минимального размера стека не хватает, то размер увеличивается на 4 K, но не более, чем до установленного директивой максимального размера. Если увеличение размера стека невозможно из-за нехватки памяти или из-за достижения его максимальной величины, генерируется исключение EStackOverflow . Минимальный размер стека по умолчанию равен 16384 (16K). Этот размер может изменяться параметром minstacksize директивы <$M>или параметром number директивы <$MINSTACKSIZE>.
    Максимальный размер стека по умолчанию равен 1,048,576 (1M). Этот размер может изменяться параметром maxstacksize директивы <$M>или параметром number директивы <$MAXSTACKSIZE number >. Значение минимального размера стека может задаваться целым числом в диапазоне между1024 и 2147483647. Значение максимального размера стека должно быть не менее минимального размера и не более 2147483647. Директивы задания размера стека могут включаться только в программу и не должны использоваться в библиотеках и модулях.

    В Delphi 1 имеется процедура компилятора <$S>, осуществляющая переключение контроля переполнения стека. Теперь этот процесс полностью автоматизирован и директива <$S>оставлена только для обратной совместимости.

    4) Директивы компилятора, включающие и выключающие генерацию информации времени выполнения о типах ( runtime type information — RTTI).

    По умолчанию <$M->или <$ TYPEINFO OFF>
    Область действия локальная

    Директивы компилятора $M включают или выключают генерацию информации времени выполнения о типах ( runtime type information — RTTI). Если класс объявляется в состоянии <$M+>или является производным от класса объявленного в этом состоянии, то компилятор генерирует RTTI о его полях, методах и свойствах, объявленных в разделе published . В противном случае раздел published в классе не допускается. Класс TPersistent , являющийся предшественником большинства классов Delphi и все классов компонентов, объявлен в модуле Classes в состоянии <$M+>. Так что для всех классов, производных от него, заботиться о директиве <$M+>не приходится.

    5) Директивы компилятора, включающие и выключающие проверку переполнения при целочисленных операциях

    По умолчанию <$Q->или <$OVERFLOWCHECKS OFF>
    Область действия локальная

    Директивы компилятора $Q включают или выключают проверку переполнения при целочисленных операциях. Под переполнением понимается получение результата, который не может сохраняться в регистре компьютера. При включенной директиве <$Q+>проверяется переполнение при целочисленных операциях +, -, *, Abs , Sqr , Succ , Pred , Inc и Dec . После каждой из этих операций размещается код, осуществляющий соответствующую проверку. Если обнаружено переполнение, то генерируется исключение EIntOverflow . Если это исключение не может быть обработано, выполнение программы завершается.
    Директивы $Q проверяют только результат арифметических операций. Обычно они используются совместно с директивами <$R>, проверяющими диапазон значений при присваивании.
    Директива <$Q+>замедляет выполнение программы и увеличивает ее размер. Поэтому обычно она используется только во время отладки программы. Однако, надо отдавать себе отчет, что отключение этой директивы приведет к появлению ошибочных результатов расчета в случаях, если переполнение действительно произойдет во время выполнении программы. Причем сообщений о подобных ошибках не будет.

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

    По умолчанию <$R>или <$RANGECHECKS OFF>
    Область действия локальная

    Директивы компилятора $R включают или выключают проверку диапазона целочисленных значений и индексов. Если включена директива <$R+>, то все индексы массивов и строк и все присваивания скалярным переменным и переменным с ограниченным диапазоном значений проверяются на соответствие значения допустимому диапазону. Если требования диапазона нарушены или присваиваемое значение слишком велико, генерируется исключение ERangeError . Если оно не может быть перехвачено, выполнение программы завершается.
    Проверка диапазона длинных строк типа Long strings не производится.
    Директива <$R+>замедляет работу приложения и увеличивает его размер. Поэтому она обычно используется только во время отладки.

    6) Директива компилятора, связывающая с выполняемым модулем файлы ресурсов

    Область действия локальная

    Директива компилятора <$R>указывает файлы ресурсов (.DFM, .RES), которые должны быть включены в выполняемый модуль или в библиотеку. Указанный файл должен быть файлом ресурсов Windows . По умолчанию расширение файлов ресурсов — .RES.
    В процессе компоновки компилированной программы или библиотеки файлы, указанные в директивах <$R>, копируются в выполняемый модуль. Компоновщик Delphi ищет эти файлы сначала в том каталоге, в котором расположен модуль, содержащий директиву <$R>, а затем в каталогах, указанных при выполнении команды главного меню Project | Options на странице Directories / Conditionals диалогового окна в опции Search path или в опции /R командной строки DCC32.
    При генерации кода модуля, содержащего форму, Delphi автоматически включает в файл . pas директиву <$R *.DFM>, обеспечивающую компоновку файлов ресурсов форм. Эту директиву нельзя удалять из текста модуля, так как в противном случае загрузочный модуль не будет создан и генерируется исключение EResNotFound .


    Все установленные в настройках опции компиляции можно вставить непосредственно в текст программы нажав клавиши Ctrl-O , O

    Как сделать свои собственные сообщения при компилляции ?

    destructor TumbSelectionTempTable.Destroy ;
    begin
    // Clear the temp tables.
    <$MESSAGE Warn ' - remember to free all allocated objects'>
    ClearAllOuterWorldFold ;
    if FSubjectsTempTableCreated then
    DropTempTable ( FTableName );

    FOuterWorldsFolded.Free ;
    FQuery.Free ;
    inherited ;
    end ;


    Работает только в Дельфи 6/7

    Как узнать версию компилятора?

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

    В Дельфи предопределены специальные константы компиляции для этого:

    Ver80 — Дельфи 1
    Ver90 — Дельфи 2
    Ver93 — С Buider 1
    Ver100 — Дельфи 3
    Ver110 — С Buider 3
    Ver120 — Дельфи 4
    Ver125 — С Buider 4
    Ver130 — Дельфи 5
    Ver140 — Дельфи 6
    Ver150 — Дельфи 7

    procedure TForm1.Button2Click( Sender : TObject );
    const Version=

    $AppType — Директива компилятора Delphi

    Решил не убирать, коли сама дельфа сгенерила, но недавно столкнулся с интересной проблемой:
    Передаваемая в процедуру

    строка менялалась после попадания, то есть результат функции после
    ее выполнения совпадал с передаваемым значением
    после этого я написал так

    не помогло, создал глобальную переменную-буфер, через которую передавал строку
    в функцию, после функции менялись обе:и буфер и оригинал
    вот так

    Так вот во всех трех переменных было одно и то же значение — расшифрованый пароль

    Добавил переменную-буфер в самих процедурах, то же самое
    Такое впечатление, что операция присвоения одной строки другой — это
    все равно что наложение адресов.

    только после замены

    все заработало нормально

    Отсюда вопрос: в чем дело? В директивах компиляции или это где-то в опциях дельфы настраивается?!

    P.S. строки типа string в Ansi кодировке

    Отсюда вопрос: в чем дело? В директивах компиляции или это где-то в опциях дельфы настраивается?!

    P.S. строки типа string в Ansi кодировке

    Дело в реализации поддержки ANSIString в Delphi.

    09.06.2008, 16:27 #2
    10.06.2008, 04:20 #3

    интересные у дельфы методы оптимизации работы со строками, это типа шоб меньше памяти занимать пока у строк одинаковое значение

    А в последующих версиях дельф тоже такая тема?

    Насколько я знаю, во всех версиях одинаково. В последующих версиях нужно спрашивать у разработчиков. Мое мнение — требования совместимости со старым кодом не дадут внести существенных изменений в этот механизм.

    Кроме того, есть же еще:

    ShortString
    array of char
    PChar
    .

    С этими типами таких проблем не возникнет .
    будут другие

    Директива компилятора Delphi для оценки аргументов в обратном порядке — delphi

    Я был очень впечатлен этим delphi двумя лайнерами, используя функцию IFThen из Math.pas. Однако сначала он оценивает DB.ReturnFieldI, что является неудачным, потому что мне нужно вызвать DB.first, чтобы получить первую запись.

    (как бессмысленное разъяснение, потому что у меня уже есть много хороших ответов. Я забыл упомянуть, что 0 — это код, который DB.First возвращает, если он что-то получил в нем, возможно, не имел смысла в противном случае)

    Очевидно, это не такая уж большая проблема, как я мог бы заставить ее работать с пятью прочными лайнерами. Но все, что мне нужно для этого, — это использовать Delphi для оценки DB.first сначала и DB.ReturnFieldI. Я не хочу менять math.pas, и я не думаю, что это гарантирует мне перегрузку, потому что там, как 16 функций.

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

      3 4
    • 19 окт 2020 2020-10-19 15:25:35
    • Peter Turner

    4 ответа

    AFAIK нет директивы компилятора для управления этим. Если вы не используете соглашения stdcall/cdecl/safecall, параметры передаются слева направо в стеке, но поскольку соглашение по регистру по умолчанию может также передавать параметры в регистрах, может случиться так, что параметр будет вычисляться позже поместить в регистр перед вызовом. И поскольку только фиксированный порядок фиксирован (EAX, EDX, ECX) для параметров, которые соответствуют критериям, регистры могут быть загружены в любом порядке. Вы могли бы попытаться принудительно использовать соглашение о вызове «pascal» (в любом случае вам нужно будет переписать функцию), но IMHO всегда опасно полагаться на такой код, если компилятор не может явно гарантировать порядок оценки. И введение порядка оценки может значительно уменьшить количество доступных оптимизаций.

    • 19 окт 2020 2020-10-19 15:25:36
    • [email protected]

    Не можете ли вы изменить свой запрос, чтобы иметь только один результат, чтобы избежать команды «Первый»? Также как:

    • 19 окт 2020 2020-10-19 15:25:36
    • philnext

    соглашение о вызове влияет на способ их оценки.
    Для этого не существует компилятора.

    Pascal — это вызов, который вы должны использовать для получения этого поведения.

    Хотя я лично никогда не буду зависеть от этого типа поведения.

    В следующей примерной программе показано, как это работает.

    Это потребует от вас написать свои собственные функции IfThen.

    Если вы действительно хотите, чтобы это был один лайнер, вы действительно можете это сделать в Delphi. Я просто думаю, что это выглядит уродливо.

    • 19 окт 2020 2020-10-19 15:25:36
    • Robert Love

    Обычно порядок оценки выражений undefined. (C и С++ аналогичны. Java всегда оценивает слева направо.) Компилятор не контролирует его. Если вам нужно два выражения для оценки в определенном порядке, напишите свой код по-разному. Я бы не стал беспокоиться о количестве строк кода. Линии дешевы; используйте столько, сколько вам нужно. Если вы часто используете этот шаблон, напишите функцию, которая завершает все:

    Ваш исходный код, вероятно, не был бы тем, что вы хотели, даже если порядок оценки был другим. Даже если DB.First не был равен нулю, вызов ReturnFieldI все равно будет оцениваться. Все фактические параметры полностью вычисляются перед вызовом функции, которая их использует.

    Изменение Math.pas все равно не поможет. Он не контролирует, в каком порядке оцениваются его фактические параметры. К тому времени, когда он их видит, они уже были оценены до логического значения и целого числа; они больше не являются исполняемыми выражениями.

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

    Соглашение о вызове pascal передает аргументы слева направо в стеке. Это означает, что самый левый аргумент находится в нижней части стека, а самый правый аргумент находится вверху, чуть ниже адреса возврата. Если функция IfThen использовала этот вызов, существует несколько способов, которыми компилятор мог бы достичь этого макета стека:

    То, как вы ожидаете, это то, что каждый аргумент оценивается и сразу же перенаправляется:

    Оцените аргументы справа налево и сохраните результаты во временном режиме до тех пор, пока они не будут нажаты:

    Сначала выделите пространство стека и оцените в любом порядке:

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

    Соглашение о вызове по умолчанию также передает аргументы слева направо, но первые три аргумента, которые соответствуют, передаются в регистры. Однако регистры, используемые для передачи аргументов, также являются реестрами, наиболее часто используемыми для оценки промежуточных выражений. Результат DB.First = 0 необходимо было передать в регистр EAX, но компилятор также нуждался в этом регистре для вызова ReturnFieldI и для вызова First . Вероятно, было бы гораздо удобнее сначала оценить вторую функцию, например:

    Еще одно замечание: ваш первый аргумент является составным выражением. Там вызов функции и сравнение. Там нечего гарантировать, что эти две части выполняются последовательно. Компилятор может сначала вызвать вызовы функций, вызвав First и ReturnFieldI , а затем сравните возвращаемое значение First с нулем.

    Delphi Директива компилятора для оценки аргументов в обратном

    Я был действительно впечатлен этим Дельфи два лайнера с помощью функции IFThen из Math.pas. Тем не менее, оценивает DB.ReturnFieldI первое, что прискорбно, потому что мне нужно вызвать DB.first, чтобы получить первую запись.

    (Как бессмысленное разъяснение, потому что у меня так много хороших ответов уже. Я забыл упомянуть, что 0 это код, который DB.First возвращается, если у него есть что-то в нем, не могу иметь смысла в противном случае)

    Очевидно, что это не такая большая проблема, как я мог заставить его работать с пятью прочными прокладками. Но все, что мне нужно для этого, чтобы работать для Delphi, чтобы оценить DB.first первый и второй DB.ReturnFieldI. Я не хочу, чтобы изменить math.pas, и я не думаю, что это гарантирует мне сделать перегруженную ifthen, потому что как 16 ifthen функций.

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

    Порядок вычисления выражений обычно не определено . (C и C ++ является таким же образом. Java всегда вычисляется слева направо.) Компилятор не предлагает никакого контроля над ним. Если вам нужно два выражения должны быть оценены в определенном порядке, а затем написать свой код по- разному. Я бы не беспокоиться о количестве строк кода. Линии дешевы; использовать столько , сколько нужно. Если вы будете использовать этот шаблон часто, написать функцию , которая оборачивает все это:

    Ваш исходный код , вероятно , не было бы то , что вы хотели, даже если порядок оценки были разными. Даже если DB.First не равен нулю, то вызов ReturnFieldI будет по- прежнему будет оцениваться. Все фактические параметры полностью оценены перед вызовом функции , которая использует их.

    Изменение Math.pas не все равно поможет. Он не контролирует, в каком порядке его фактические параметры вычисляются в К тому времени он видит их, они уже были оценены до логического значения и целое. они не исполняемое выражения больше.

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

    Паскаль соглашение о вызовах передает аргументы влево-вправо на стеке. Это означает , что крайний левый аргумент один в нижней части стека, а крайний правый аргумент в верхней, чуть ниже обратного адреса. Если IfThen функция используется , что соглашение о вызове, есть несколько способов , компилятор может достичь этого макета стека:

    То, как вы ожидаете, что это то, что каждый аргумент вычисляется и толкнул сразу:

    Оценивать аргументы справа налево и сохранить результаты в временных, пока они не толкнули:

    Выделяют пространство стека первым, и оценить в любом порядке, удобно:

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

    Регистр по умолчанию соглашение о вызовах также передает аргументы влево-вправо, но первые три аргумента , которые соответствуют передаются в регистрах. Регистры , используемые для передачи аргументов, хотя, также регистры , наиболее часто используемые для оценки промежуточных выражений. Результат DB.First = 0 должен был быть передан в регистр EAX, но компилятор также нужен этот регистр для вызова ReturnFieldI и для вызова First . Вероятно , это был немного более удобным , чтобы оценить вторую функцию первой, как это:

    Еще одна вещь , чтобы указать на то , что ваш первый аргумент является выражение соединения. Там есть вызов функции и сравнение. Там нет ничего , чтобы гарантировать , что эти две части выполняются последовательно. Компилятор может получить вызовы функций из пути первого по телефону First и ReturnFieldI , а потом сравнить First возвращаемое значение от нуля.

    Илон Маск рекомендует:  Информационные блоки предупреждений
    Понравилась статья? Поделиться с друзьями:
    Кодинг, CSS и SQL
    10.06.2008, 09:41 #4