Препроцессорные директивы (макросы)

Инструкции препроцессора называются директивами. Они начинаются с символа # и выполнение их происходит на этапе компиляции. Мы уже сталкивались ранее в статьях с директивами препроцессора: #include и #inclib, но давайте рассмотрим их. И не только их.

 

#INCLUDE

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

Пример:

#INCLUDE "windows.bi"

 

#INCLIB

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

Пример:

#INCLIB "opengl32"

 

#LIBPATH

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

Пример:

#libpath"C:\"
#INCLIB "AAAA"

 

#PRINT

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

Пример:

#PRINT file_1.bas full compiling


Кавычки для строки file_1.bas full compiling  не требуются. Теперь если поместить всю эту строку в конец исходного кода, то после компиляции в окне команд будет высвечиваться эта надпись, оповещающая, что файл откомпилирован.

 

#ERROR

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

Пример:

#ERROR file 2.bi Not found

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

 

#DEFINE

Эта директива позволяет определить макрос. Макросы часто используются программистами для облегчения понимания кода, да и самого программирования тоже. Макрос позволяет заменить сложную строку с командами или просто какую то строку, простым и понятным именем. Так к примеру макрос  RGB (r,g,b) представляет из себя реальную запись:

(Cuint(r) Shl 16) Or (Cuint(g) Shl 8) Or Cuint(b) Or &hFF000000


Сами понимаете как удобнее записывать. С помощью #define можно определять все что хочется. На самом деле немалая часть встроенных команд языка Freebasic - это определенные макросы.
Определяются макросы записью, начинающейся с #define.  Далее следует имя макроса, которое в дальнейшем будет использоваться в нужных местах кода. И наконец значение, которое при компиляции будет подставляться в код вместо имени.

Пример простого макроса:

#DEFINE PI 3.1415926535897932


Теперь где бы мы не вставляли слово PI , при компиляции будет заменено на настоящее значение 3.14.....

При объявлении макроса можно производить любые действия:

#DEFINE SummaString(x,y) Str(x)+Str(y)
? SummaString(167,382)
? SummaString("Ivan"," Sidorov")
Sleep

 

#MACRO

#define конечно удобен для создания макроса, но часто нужен макрос, состоящий из большого числа строк. В этом случае может выручить блок #macro - #endmacro.

Пример_1 (без параметров):

#INCLUDE "windows.bi"

#MACRO Text()
"Однажды Мастер Никеда сказал своим ученикам:" & !"\r\n" &_
"— В мире нет Абсолютной Истины." & !"\r\n" &_
"Один из учеников спросил:" & !"\r\n" &_
"— А эта истина абсолютна?" & !"\r\n" &_
"— Нет, конечно, — улыбнулся Мастер." & !"\r\n"
#ENDMACRO

MessageBox(0,Text(),"Притча",0)

В этом примере записан макрос Text , которой представляет из себя форматированный текст. Не пугайтесь записи !"\r\n" это форматирующие символы для перевода строк. Вместо этого можно было записать так: chr(13) & chr(10)

Пример_2 (с параметрами):

#MACRO SWAP_(a,b)
   Scope
      Var c=a
      a=b
      b=c
   End Scope
#ENDMACRO
Dim As Integer x=10,y=20
SWAP_(x,y)
? x,y
Sleep


В примере выше макрос обменивает значения у переменных.

 

#UNDEF

Данная директива позволяет отменять объявленный макрос.

Пример:

#INCLUDE "windows.bi"
#Undef Print
#DEFINE Print(a) MessageBox(0,a,"",0)
Print ("FreeBasic")

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

 

#iF , #ELSEIF , #ELSE, #ENDIF , #iFDEF ,  #IFNDEF И DEFINED

Директивы условной компиляции предназначены для включения или отключения компиляции отдельных частей в зависимости например от платформы, или от версии программы. Объяснять суть #If , #elseif , #else, #endif наверно не стоит. Если вы читали статью о логических операторах , то смысл их работы должен быть понятен. Единственно что стоит упомянуть: при использовании этих директив не нужно (нельзя) указывать THEN.

Пример:

#DEFINE version lite
#IF version=lite
   #PRINT Start compile lite version
#ELSE
  #PRINT Start compile full version
#ENDIF


Директивы:

#IFDEF - если объявлена
#IFNDEF - если не объявлена
DEFINED - если объявлена

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

Пример_1:

Dim a As Integer
#IFNDEF a
  Dim a As Integer
#ELSE
  Print "a declared"
#ENDIF
Sleep


Пример_2:

Const a As Integer=45
#IF DEFINED(a)
  Print "a declared"
#ELSE
  Print "a not declared"
#ENDIF
Sleep

 

Предопределенные макросы

Эти макросы выдают информацию о платформе, версии компилятора , процессе компиляции и др.

Используемые для проверки платформы:
 
__FB_WIN32__  - Windows
__FB_LINUX__  - Linux
__FB_DOS__      - DOS

Есть еще макросы определения других платформ, однако эти платформы не используются в FreeBasic, если интересно читаем в справке.

Пример:

#IFDEF __FB_WIN32__
   ' объявления и инструкции для платформы Windows
#ELSEIF __FB_LINUX__
   ' объявления и инструкции для платформы Linux
#ENDIF


Связанные с получением информации о версии компилятора:

  • __FB_VERSION__  - возвращает версию компилятора
  • __FB_VER_MAJOR__  - возвращает номер версии
  • __FB_VER_MINOR__  - возвращает расширение номера версии
  • __FB_VER_PATCH__  - возвращает версию обновления
  • __FB_MIN_VERSION__( major, minor, patch)  - устанавливает минимальную версию для компиляции
  • __FB_BUILD_DATE__  - возвращает дату компиляции в формате день-месяц-год
  • __FB_SIGNATURE__  - возвращает версию компилятора по сигнатуре


Пример:

Print __FB_VERSION__  'версия компилятора
Print __FB_VER_MAJOR__  ' номер версии
Print __FB_VER_MINOR__  ' расширение номера версии
Print __FB_VER_PATCH__  ' версия обновления
Print __FB_BUILD_DATE__  ' дата компиляции 
Print __FB_SIGNATURE__  ' версия компилятора по сигнатуре
#IF __FB_MIN_VERSION__(0, 22, 0)'ставим минимальную версию 0.22
     #PRINT Start compiling
#ENDIF
Sleep

Связанные с получением информации о текущем компилируемом модуле:

  • __FB_MAIN__  -  определение компилирования главного модуля
  • __FB_DEBUG__  - определяет режим компиляции с отладочной информацией.  Если была определена опция возвращает -1
  • __FB_ERR__  - возвращает режим включения проверки ошибок: (0,1,3,7)
    • 0 - не используется
    • 1 - выборочный режим отлова ошибок
    • 3 - стиль Qbasic
    • 7 - проверка ошибок по максимуму
  • __FB_LANG__  - возвращает языковый режим совместимости
    • ''fb''  - Freebasic
    • ''qb'' - Совместимая с Qbasic
    • ''fblite'' - Версия более или менее совместимая с Qbasic
    • ''deprecated'' - Прошлые версии FreeBasic
  • __FB_MT__  - определяет использование RunTime Library для многопоточных приложений. Если была определена опция возвращает -1
  • __FB_OUT_DLL__  - определяет что компилируется DLL . Если была определена опция возвращает -1
  • __FB_OUT_EXE__  - определяет что компилируется EXE . Если была определена опция возвращает -1
  • __FB_OUT_LIB__  -  определяет что компилируется статическая библиотека . Если была определена опция возвращает -1
  • __FB_OUT_OBJ__  - определяет что компилируется объектный файл. Если была определена опция возвращает -1

 Пример:

#IFDEF __FB_MAIN__  
#PRINT Main module
#ENDIF

#IF __FB_DEBUG__ 
#PRINT Debug mode
#ELSE
#PRINT Not Debug mode
#ENDIF

#IF __FB_ERR__ =0 
#PRINT Not Checking
#ELSEIF __FB_ERR__ =1
#PRINT Some Checking
#ELSEIF __FB_ERR__ =3
#PRINT Qbasic Style Checking
#ELSEIF __FB_ERR__ =7
#PRINT SuperChecking
#ENDIF

#IF __FB_LANG__ ="fb" 
#PRINT Using Modern FreeBasic
#ELSEIF __FB_LANG__ ="qb"
#PRINT Using Qbasic
#ELSEIF __FB_LANG__ ="fblite"
#PRINT Using FreeBasic Some compatibility QBasic
#ELSEIF __FB_LANG__ ="deprecated"
#PRINT Using old FreeBasic
#ENDIF

#IF __FB_MT__ =-1
#PRINT Using multi-threaded library
#ENDIF

#IF __FB_MT__ =-1
#PRINT Using multi-threaded library
#ENDIF

#IF __FB_OUT_DLL__ =-1
#PRINT Compile DLL Library
#ELSEIF __FB_OUT_EXE__ =-1
#PRINT Compile EXE file
#ELSEIF __FB_OUT_LIB__ =-1
#PRINT Compile Static Library
#ELSEIF __FB_OUT_OBJ__ =-1
#PRINT Compile Object file
#ENDIF

После компиляции этого примера с такой командой: fbc -s console , в командной строке должно высветиться:

fbc -s console "FbTemp.bas"
Main module
Not Debug mode
Not Checking
Using Modern FreeBasic
Compile EXE file

Make done

 

Другие макросы

  • __DATE__ - возвращает дату компиляции
  • __TIME__  - возвращает время компиляции
  • __PATH__ - возвращает путь к исходному файлу
  • __FILE__ - возвращает имя текущего файла с кавычками
  • __FILE_NQ__ - возвращает имя текущего файла без кавычек. Нельзя использовать для обычной команды Print
  • __FUNCTION__ - возвращает название функции с кавычками в которой записана
  • __FUNCTION_NQ__ -  возвращает название функции без кавычек в которой записана. Может использоваться для получения адреса функции, но нельзя использовать для обычной команды Print
  • __LINE__ - возвращает номер строки на которой записана


Пример:

? __DATE__ 
? __TIME__  
? __PATH__ 
? __FILE__
? __LINE__
#PRINT __FILE_NQ__ 

Sub MySub
  Print "Address of " + __FUNCTION__ + " is ";
  Print Hex( @__FUNCTION_NQ__ )
End Sub
MySub
Sleep


Это все по макросам. Всего доброго!

содержание | назад | вперед