Директивы компилятора
   
Директивы компилятора  
Режимы компиляции. Отладка.  
Универсальность кода  
Эмуляция сопроцессора  
Оптимизация  
   


Директивы компилятора

(by Altair)
Почему-то мало кто пользуется директивами компилятора в полном масштабе...

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

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

Общий синтаксис этих команд таков:


Режимы компиляции. Отладка.

Предположим, что в программе необходимо на этапе отладки выводить какие-то данные для тестирования алгоритма... Можно, конечно, в окончательном варианте кода закомментировать такие отладочные выводы, или удалить, но лучше заключить "отладочные операторы" в такую конструкцию, с использованием директив:
{$define debug}
var
  x:byte;
begin
  x:=1;
  inc(x);
  {$ifdef debug}
    writeln(x);
  {$endif}
end.
Таким образом, при работе программы на экран будет выведено значение "2". Если отладку надо отменить, мы можем убрать символ "$" из директивы {$define debug} - и теперь это будет просто коментарий, и следовательно на экран ничего не будет выведено.


Универсальность кода

Хорошо, когда мы берем старый код из TP и он компилируется, и программа правильно работает в компиляторе постарше...

А почему бы не реализовать совместимость наоборот или напрямую? Часто при компиляции, возникают ошибки только из-за того, что код оптимизирован под конкретный компилятор, например под BP, и в TP отказывается компилироваться...

Выходом из такой ситуации является правильное написание кода, а именно отладка кода под различные компиляторы (конечно если это требуется). Для примера рассмотрим программу для построения графиков некоторых функций (в полярной системе координат):
{$ifdef Win32}
  {$APPTYPE GUI}
{$else}
  {$E+} {$N+}
{$endif}
Uses
  {$ifdef Win32}
    WinCrt,Windows,
  {$else}
  CRT,
  {$endif}
  Graph;
Var {GLOBAL}
  Gd,Gm:Integer;
  a,b:Longint;
  g:byte;

Procedure INIT;
begin
  {$ifdef Win32}
    gd:=d8bit; gm:=m800x600;
  {$else}
    gd:=Vga; Gm:=VgaHi;
  {$endif}
  InitGraph(gd,gm,'');
  SetColor(11);
  SetBkColor(8);
End; {INIT}

Procedure Graphic;

 Function Ro(Fi:Double):Double;
 begin
   case g of
     1:ro:=fi;
     2:ro:=Sin(7*fi);
     3:ro:=1-cos(fi);
     4:ro:=5*cos(fi)+2;
     5:if cos(2*fi)>=0 then ro:=sqrt(2*cos(2*fi));
   end;
 end;
 
Const
  c=2*pi; step=0.0005;
  r=220;
  {$ifdef Win32}
    x0=400; y0=300;
  {$else}
    x0=320; y0=220;
  {$endif}
var
  k, max, fi: Double;
  
Begin
  fi:=0; max:=0.0001;
  repeat
    if max < abs(ro(fi)) then max:=abs(ro(fi));
    fi:=fi+0.01
  until fi > c;

  fi:=0;
  repeat
    k:=ro(fi)/max;
    if k < 1 then putpixel(x0+Round(r*cos(a*fi)*k),
                              y0+Round(r*sin(b*fi)*k),15);
    If Keypressed then Exit else fi:=fi+step
  until fi > c
end; {graphic}

Begin
  INIT;
  Repeat
    clearViewPort;
    Outtextxy(20,14,'Case graphic:');
    Outtextxy(20,22,'1. Spiral Arhimeda');
    Outtextxy(20,30,'2. seeds petal rose');
    Outtextxy(20,38,'3. Kardioida');
    Outtextxy(20,46,'4. Snail Pascal');
    Outtextxy(20,54,'5. Lemniskatta Bernuli');
    g:=ord(readkey)-48;
    a:=5; b:=5;
    clearViewPort;
    Graphic;
    Outtextxy(20,450,'Esc-exit, Enter-repeat')
  until readkey=#27;
  CloseGraph
end.
Этот код можно скомпилировать вот в этих компиляторах: FPC(target: Win32, DOS), TP7, BP7, BPW (target:real, protected mode), TMT. Неплохо, правда? И везде он будет работать одинаково правильно!

Конечно при компиляции в FPC под Win32, это будет Windows-приложение, а в остальных случаях консольное DOS (16 битное) приложение...

Прокоментирую первые строчки программы (а дальше я думаю все понятно):
{$ifdef Win32}   { - если компилируем под Win32                         }
                 {  (это сработает только в FPC, TMT)                   }
  {$APPTYPE GUI} { - режим компиляции: графическое Windows приложение.  }
{$else}          { - компилируем в 16 битных компиляторах.              }
  {$E+} {$N+}    { - включаем эмуляцию сопроцессора, т.к.
                     в программе используются тип double                }
{$endif}         { - конец условного участка кода.                      }

Uses
{$ifdef Win32}     { - если компилируем под Win32                       }
  WinCrt, Windows, {   подключаем соотв. модули.                        }
{$else}            { - иначе компиляция в 16 битных компиляторах        }
  CRT, 
{$endif}           { - конец условного куска кода.                      }
  Graph;           { - а этот модуль подключается в любом случае.       }


Эмуляция сопроцессора

Очень часто у многих возникает вопрос - почему при компиляции у меня возникает ошибка "Error 116: Must be in 8087 mode to compile this" ?

Ответ: Вы используете один из следующих вещественных типов: Single, Double, Extended, или Comp. Для работы с этими типами необходима эмуляция сопроцессора. Просто добавьте в начало программы директивы: {$E+, $N+}


Оптимизация

Для уменьшения размера программ (и оптимизации по скорости) можно пользоваться следующими директивами:

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

Директивы с параметрами





Free Web Hosting