Директива #include
#include </*имя заголовочного файла*/>
Директива #include
вставляет код из указанного файла в текущий файл, то есть, просто подключив другой файл, мы можем пользоваться его функциями, классами, переменными. Заголовочные файлы обычно находятся либо в текущей директории, либо в стандартном системном каталоге.
Подключение заголовочных файлов выполняется во время компиляции, либо как файл, который является частью вашего проекта. Эта функция зависит от конкретной реализации вашего компилятора, поэтому для получения более подробной информации, покопайтесь в настройках своего компилятора.
Если подключаемый файл не найден, процесс компиляции завершается с ошибкой.
Директива #define
Директива #define
принимает две формы:
- определение констант;
- определение макросов.
Определение констант
#define nameToken value
При использовании имени константы — nameToken
, оно будет заменено значением value
, то есть, грубо говоря — это та же самая переменная, значение которой изменить нельзя. Смотрим пример использования константы:
#include <iostream> #define TEXT "Марс" // определение константы int main() { std::cout << TEXT; return 0; }
Как видите, для доступа к значению константы, просто используем её имя.
Определение параметризованных макросов
#define nameMacros(arg1, arg2, ... ) expression
К примеру определим макрос, который будет возвращать максимальное из двух значений.
#define MAX(num1, num2) ((num1) > (num2) ? (num1) : (num2))
Внимание, для определения многострочного макроса, в каждой строке, в конце, должен ставиться символ , что сообщает препроцессору, что макрос еще не завершен.
Директива #undef
Директива #undef
переопределяет константу или препроцессорный макрос, ранее определенный с помощью директивы #define
.
#undef nameToken
Давайте посмотрим пример использования директивы #undef
:
#define E 2.71828 // раннее определенный макрос int sumE = E + E; // обращение к макросу #undef E // теперь E - не макрос
Как правило, директива #undef
используются для снятия, ранее определенной константы или макроса, в небольшой области программы. Это делается для того, чтобы для всей программы, макроc или константа оставались, а для некоторой области, эти же макрос или константа могут быть переопределены. Небезопасно было бы во всей программе переопределять константу, но в короткий области, это сравнительно безопасно. Директива #undef
является единственным способом создания этой области, так как область действия макросов или констант действует от директивы #define
до #undef
.
Директива #if
#if value // код, который выполнится, в случае, если value - истина #elsif value1 // этот код выполнится, в случае, если value1 - истина #else // код, который выполнится в противном случае #endif
Директива #if
проверяет, является ли значение value
истиной и, если это так, то выполняется код, который стоит до закрывающей директивы #endif
. В противном случае, код внутри #if
не будет компилироваться, он будет удален компилятором, но это не влияет на исходный код в исходнике.
Обратите внимание, что в #if
могут быть вложенные директивы #elsif
и #else
. Ниже показан пример кода для комментирования блоков кода, используя следующую конструкцию:
#if 0 // код, который необходимо закомментировать #endif
Если у вас в программе есть блоки кода, которые содержат многострочные комментарии и вам требуется обернуть полностью этот блок кода в комментарий — ничего не получится, если вы воспользуетесь /*многострочный комментарий*/
. Другое дело — конструкция директив #if #endif
.
Директива #ifdef
#ifdef nameToken // код, который выполнится, если nameToken определен #else // код, который выполнится, если nameToken не определен #endif
Директива #ifdef
проверяет, был ли ранее определен макрос или символическая константа как #define
. Если — да, компилятор включает в программу код, который находится между директивами #ifdef
и #else
, если nameToken
ранее определен не был, то выполняется код между #else
и #endif
, или, если нет директивы #else
, компилятор сразу переходит к #endif
. Например, макрос __cpp
определен в C++, но не в Си. Вы можете использовать этот факт для смешивания C и C++ кода, используя директиву #ifdef
:
#ifdef __cpp // C++ код #else // Си код #endif
Директива #ifndef
#ifndef nameToken // код, который выполнится, если nameToken не определен #else // код, который выполнится, если nameToken определен #endif
Директива #ifndef
проверяет, был ли ранее определен макрос или символическая константа как #define
. Если — да, компилятор включает в программу код, который находится между директивами #else
и #endif
, если nameToken
ранее определен не был, то выполняется код между #ifndef
и #else
, или, если нет директивы #else
, компилятор сразу переходит к #endif
. Директива #ifndef
может быть использована для подключения заголовочных файлов. если они не подключены, для этого использовать символическую константу, как индикатор подключенного к проекту функционала.
Например, в заголовочном файле есть интерфейс класса, который необходимо подключить к проекту, если ранее этот класс не был подключен.
#ifndef PRODUCT_H #define PRODUCT_H class Product { // код класса... }; #endif PRODUCT_H
В этом случае используется пустая символьная константа PRODUCT_H
, которая может быть определена в программе только вместе с классом Product
. Поэтому, если мы обнаружим, что константа PRODUCT_H
уже определена, значит класс тоже и тогда мы исключим повторное определение класса, которое может привести к ошибке переопределения.
Директива #error
#error "Этот код не должен компилироваться"
Директива #error
позволяет отображать в списке ошибок компиляции сообщение, в случае возникновения соответствующей ошибки. Эту директиву наиболее полезно использовать в сочетании с директивами #if
, #elsif
, #else
для проверки компиляции, если некоторое условие не верно. Например:
#ifndef __unix__ // __unix__ обычно поддерживается в юникс-системах #error "Поддерживается только в Unix" #endif
Препроцессорный макрос __FILE__
Препроцессорный макрос __FILE__
расширяется до полного пути к текущему файлу (исходнику). __FILE__
полезен при создании лог-файла, генерации сообщений об ошибках, предназначенных для программистов, при отладки кода.
int error (const char* adrFile, const std::string& erMessage) { cerr << "[" << adrFile << "]" << arMessage << endl; } #define LOG( erMessage ) error( __FILE__, arMessage ) // макрос LOG может быть использован для получения сообщений об ошибках, которые выводятся на стандартный поток ошибок
Макрос __FILE__
часто используется совместно с макросом __LINE__
, который предоставляет номер текущей строки.
Препроцессорный макрос __LINE__
Макрос __LINE__
разворачивается в текущий номер строки в исходном файле, как целое значение. __LINE__
полезен при создании лог-файла или генерации сообщений об ошибках с указанием номера строки, предназначенных для программистов, при отладки кода.
int error (int nLine, const std::string& erMessage) { cerr << "[" << nLine << "]" << erMessage << endl; } #define LOG( erMessage ) error( __LINE__, erMessage ) // макрос LOG может быть использован для получения сообщений об ошибках, с указанием номеров строк, которые выводятся на стандартный поток ошибок
Макрос __LINE__
часто используется совместно с макросом __FILE__
, который показывает адрес текущего исходного файла.
Препроцессорный макрос __DATE__
Макрос __DATE__
раскрывается в текущую дату (время компиляции) в виде [ммм дд гггг] (например, «Dec 7 2012″), как строка. __DATE__
может быть использован для предоставления информации о времени компиляции.
cout << __DATE__ << endl;
Вы можете также использовать макрос __TIME__
, чтобы получить текущее время компиляции.
Препроцессорный макрос __TIME__
Макрос __TIME__
раскрывается в текущее время (время компиляции) в формате чч: мм:cc
в 24-часовом формате (например, «22:29:12″). Макрос __TIME__
может быть использован для предоставления информации о времени в конкретный момент компиляции.
cout << __TIME__ << endl;
Препроцессорный макрос __TIMESTAMP__
Макрос __TIMESTAMP__
раскрывается в текущее время (время компиляции) в формате Ddd Mmm Date hh::mm::ss yyyy, время в 24-часовом формате:
Ddd
это сокращенно день недели,ммм
это сокращенно месяц ,Date
— текущий день месяца (1-31),гггг
— это четыре цифры года.
Например, "Fri Dec 7 00:42:53 2012"
. Макрос __TIMESTAMP__
может быть использован для получения информации о дате и времени компиляции.
cout << __TIMESTAMP__ << endl;
Вы можете также использовать макрос __TIME__
, чтобы получить текущее время компиляции и макрос __DATE__
для получения даты.
Директива #pragma
#pragma compiler specific extension
Директива #pragma
используется для доступа к специфическим расширениям компилятора. Совместное использование директивы #pragma
c лексемой once
просит компилятор включить файл заголовка только один раз, независимо от того, сколько раз она был импортирован:
#pragma once // заголовочный файл
В этом примере, директива #pragma once
не позволяет включать файл в проект несколько раз, то есть предотвращает переопределение.
Директива #pragma
также может быть использована для других целей, например #pragma
обычно используется для отключения предупреждений. Например, в MVS:
#pragma warning (disable : 4018 )
Директива #pragma
в этом примере используется для отключения предупреждений 4018. Для получения дополнительной использования директивы #pragma
, обратитесь к документации вашего компилятора.
Макро оператор #
#<token>
Оператор #
текстовую лексему в строку, заключенную в кавычку. Смотрим пример:
#include <iostream> using namespace std; #define message(s) cout << "Сообщение: " #s << endl; int main() { message("GunGame"); return 0; }
Выполняется конкатенация строк и макрос message
разворачивается в cout << "Сообщение: GunGamen";
. Обратите внимание на то, что операция #
должна использоваться совместно с аргументами, так как #
ссылается на аргумент.
Макро оператор ##
Оператор ##
принимает две отдельных лексемы и склеивает их вместе, чтобы сформировать один макрос. В результате может получиться имя переменной, имя класса или любой другой идентификатор. Например:
#define type ch##ar type a; // переменная a тип данных char, так как ch и ar склеились в char
Рассмотрим еще один пример использования оператора ##
, в котором объединим две лексемы:
#define TOKENCONCAT(x,y) x##y
Когда в программе выполняется вызов этого макроса, две лексемы объединяются в одну. Операция ##
обязательно должна иметь два операнда.
P.S.: Любая серьёзная программа должна иметь свою базу данных, обычно для управления БД используются следующие СУБД: MySQL, MsSQL, PostgreeSQL, Oracle и др. В установке sql server, форум на cyberforum.ru будет для вас не заменимым помощником. Задавайте свои вопросы на этом форуме, вам обязательно помогут в решении вашей проблемы.
Комментарии
yurasik90
#elsif не везде работает, можно заменить на #elif