Использование препроцессора
Здесь перечислены директивы препроцессора, которые поддерживают Tibbo BASIC и Tibbo C.
#define
Создаёт макрос - связь идентификатора препроцессора со строкой токенов.
#define RED 0
#define GREEN 1
#define BLUE 2
#define COLOR BLUE
В TIDE есть и «глобальные» идентификаторы препроцессора. Их можно просмотреть в диалоге Customize Project (File > Project Settings - > Customize (button)).
В диалоге показаны глобальные идентификаторы, которые поступают непосредственно из файлов платформы. Значения некоторых идентификаторов можно изменять. Можно также определять собственные глобальные идентификаторы.
Как и идентификаторы, определённые директивой #define, все эти глобальные идентификаторы можно использовать в описанных ниже условных конструкциях препроцессора.
Отличие идентификаторов препроцессора, определённых директивой #define, от глобальных в том, что глобальные идентификаторы можно дополнительно использовать для задания условий компиляции файлов.
#undef
Отменяет (удаляет) текущее определение идентификатора препроцессора.
#define GREEN 1
...
#undef GREEN
#ifdef-#else-#endif
Конструкция условной компиляции, проверяющая, существует ли указанный идентификатор препроцессора.
#define GREEN 1
...
dim s as string
#ifdef GREEN
'code here will be included
s="GREEN is defined"
#else
'code here will not be included
s="GREEN is not defined"
#endif
#define GREEN 1
...
string s;
#ifdef GREEN
//code here will be included
s="GREEN is defined";
#else
//code here will not be included
s="GREEN is not defined";
#endif
#if defined (только C)
Более продвинутая версия #ifdef, позволяющая задавать составные условия.
Обратите внимание: в конструкции #if defined идентификаторы макросов необходимо заключать в скобки.
#define PRINTER 1
#if defined(PRINTER) && !defined(ABC)
'code here will be included
#endif
#ifndef-#else-#endif
Конструкция условной компиляции, проверяющая, что указанного идентификатора препроцессора не существует.
#define GREEN 1
...
dim s as string
#ifndef GREEN
'code here will not be included
s="GREEN is not defined"
#else
'code here will be included
s="GREEN is defined"
#endif
#define GREEN 1
...
string s;
#ifndef GREEN
//code here will not be included
s="GREEN is not defined";
#else
//code here will be included
s="GREEN is defined";
#endif
#if-#elif-#else-#endif
Конструкция условной компиляции, вычисляющая выражение с идентификаторами препроцессора.
Напоминание: некоторые операторы сравнения и логические операторы в BASIC и C различаются. То, что в BASIC записывается как #if COLOR=RED, в C будет #if COLOR==RED!
#define RED 0
#define GREEN 1
#define BLUE 2
#define COLOR GREEN
#if COLOR=RED
'code here will not be included
#elif COLOR=GREEN
'code here will be included
#else
'code here will not be included
#endif
#define RED 0
#define GREEN 1
#define BLUE 2
#define COLOR GREEN
#if COLOR==RED
//code here will not be included
#elif COLOR==GREEN
//code here will be included
#else
//code here will not be included
#endif
#include (C); include (BASIC)
В BASIC файлы подключаются оператором include, который формально не является частью препроцессора.
Здесь он рассматривается вместе с директивой препроцессора C #include, потому что выполняют они совершенно одну и ту же работу.
'remember, headers files must be included,
'it's not enough to just have them in the project tree
include "global.tbh"
//remember, headers files must be included,
//it's not enough to just have them in the project tree
#include "global.tbh"
#includeb (только C)
Позволяет подключить заголовочный файл BASIC (.TBH) из файла C. Это мощный инструмент: с ним не нужно держать два одинаковых заголовочных файла с определениями - один для BASIC и зеркальный для C.
Обратной директивы, подключающей заголовки C из файлов BASIC, не существует.
dim ctr as byte
include "global.tbh"
sub on_sys_init
ctr=0
end sub
#includeb "global.tbh"
void on_sys_timer(){
ctr++; //a separate declaration of ctr in the C style is not required
}
#includepp
Особенность препроцессора Tibbo - директивы препроцессора можно включать в текстовые файлы ресурсов.
Это широко применяется в библиотеках. Например, библиотека STG опирается на settings.xtxt - файл определений со списком настроек, их именами, типами и так далее.
Обычно с этим файлом работают через удобный конфигуратор. Если заглянуть в содержимое самого текстового файла, там можно увидеть несколько директив #define.
Чтобы TIDE распознал эти директивы, нужно включить этот текстовый файл ресурсов в процесс компиляции директивой includepp.
includepp "settings.xtxt"
'define an arrays with the number of elements equal to the #define made in a
'text resource file
dim arr(STG_MAX_NUM_SETTINGS) as byte
#includepp "settings.xtxt"
//define an arrays with the number of elements equal to the #define made in a
//text resource file
unsigned char arr[STG_MAX_NUM_SETTINGS];
...
#define STG_MAX_NUM_SETTINGS 40
#message
Выводит сообщение на панель Output (не забудьте заключить строку сообщения в "").
...
#if COLOR=RED
#message "The color is RED"
#elif COLOR=GREEN
#message "The color is GREEN"
#else
#message "The color is BLUE"
#endif
...
#if COLOR==RED
#message "The color is RED"
#elif COLOR==GREEN
#message "The color is GREEN"
#else
#message "The color is BLUE"
#endif
Пример вывода компилятора (сокращённо) для приведённого выше кода:
Compiling main.tbs...
(prj)\main.tbs(4): message: The color is BLUE
Linking...
Build complete.
#error
Выводит сообщение на панель Output и прерывает компиляцию (не забудьте заключить строку сообщения в "").
...
#if COLOR=RED
#message "The color is RED"
#elif COLOR=GREEN
#message "The color is GREEN"
#elif COLOR=BLUE
#message "The color is BLUE"
#else
#error "Unsupported color. Compilation aborted."
#endif
...
#if COLOR==RED
#message "The color is RED"
#elif COLOR==GREEN
#message "The color is GREEN"
#elif COLOR==BLUE
#message "The color is BLUE"
#else
#error "Unsupported color. Compilation aborted."
#endif
Пример вывода компилятора (сокращённо) для приведённого выше кода:
Compiling c.tc...
(prj)\c.tc(142): #error: Unsupported color. Compilation aborted.
#pragma pack (только C)
Возможные значения: #pragma pack (1), (2) или (4).
Указание #pragma pack (2) приводит к 16-битному выравниванию в структурах и объединениях (для правильного выравнивания добавляются нулевые байты заполнения).
Использование #pragma pack (4) приведёт к 32-битному выравниванию.
В Tibbo BASIC такой конструкции нет, поскольку там применяются «безопасные» структуры со специальными заголовками. Для таких «безопасных» структур «упаковка» не имела бы смысла.
В Tibbo C по умолчанию действует (1), то есть никакого заполнения нет.
struct test_unpacked{
unsigned char x; //occupies one byte
unsigned long l; //occupies four bytes
};
#pragma pack (4) //this will affect all definitions below
struct test_packed{ //this structure will be with padding
unsigned char x; //occupies one byte
unsigned long l; //occupies four bytes
};
test_unpacked tu;
test_packed tp;
void on_sys_timer(){
sys.debugprint(str(sizeof(tu))+", "); //Will print "5" (unsigned char + unsigned long need 5 bytes)
sys.debugprint(str(sizeof(tp))); //Will print "8" because 3 padding bytes will be added after the unsigned char
}
При #pragma pack (4) и значениях tp.x=0x12 и tp.l=0x3456789A структура памяти, содержащая переменную tp, будет выглядеть так (обратите внимание на три нулевых байта заполнения):
| 0x12 | 0x00 | 0x00 | 0x00 | 0x9A | 0x78 | 0x56 | 0x34 |
#pragma message (только C)
Существует для совместимости с другими реализациями C; того же результата можно добиться директивой #message.