Лекция 12. Препроцессор (1115006)
Текст из файла
Лекция 12. ПрепроцессорМакросы и почему их не стоитиспользоватьValery Lesin. C++ In-Depth, 20141Использование макросов• Никогда не пользуйтесь макросами, если Выможете этого не делать• Макросы обрабатываются препроцессором докомпиляции. Поэтому они ничего не знают нио пространстве имен, ни о типах.• Такие средства, как константы, inline функции,шаблоны и т.д. были призваны заменитьиспользование макросов.• Отладочные средства (например, дебагер) исредства разработки часто не могут заглянутьвнутрь макроса.Valery Lesin. C++ In-Depth, 20142Применимость макросов• Когда макросы полезны– Включение файлов и #include guard– Конкатенация токенов– Отладочный вывод– Условная компиляция• Есть три типа макросов: директивы, макроконстанты и макро-функцииValery Lesin.
C++ In-Depth, 20143Определение констант• Простой синтаксис#define <identifier name> [value]• Символ # должен быть первым в строке (кроме пробельных),можно также вставлять whitespace между # и define.• Можно определить и без значения - используется дляусловной компиляции.• Будьте осторожны с контекстом - ставьте скобки.1.2.3.4.5.6.#define PI3.1415926#define PI_PLUS_1 PI + 1x = PI_PLUS_1 * 5; // results in PI + 1 * 5 (Oops!)// do like this#define PI_PLUS_2 (PI + 2)Valery Lesin. C++ In-Depth, 20144Условная компиляция• Незаменима при кроссплатформенной разработке• Помогает настроить версии используемых библиотек, платформу,операционную систему и т.д.• Можно использовать для временного комментиорвания кода1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.#ifdef WIN32#ifdef _MSC_VER > 1800//...#endif // _MSC_VER#else//...#endif // WIN32// boolean expressions#if defined (__linux__) && !defined(NDEBUG)//...#if 0/* ...
*/ //...#endifValery Lesin. C++ In-Depth, 20145include guard• Позоляют избежать повторного включения хидера в кодединицы трансляции• Тот же эффект, что и #pragma once1.2.3.4.5.#ifndef __MY_INCLUDE_H__#define __MY_INCLUDE_H__// C++ header body#endif // __MY_INCLUDE_H__Valery Lesin. C++ In-Depth, 20146Макро функции• Определяется почти как константа#define MACRO_NAME(arg1, arg2, ...) [code to expand to]• Нельзя перегружать• Не работает с рекурсией• Не понимает шаблонов *• Не вычисляет аргументы перед вызовом - подставляется какесть1.2.3.4.5.6.7.8.#define MAX(a,b) a > b ? a : bMAX(x + 4, x--);// results inx + 4 > x-- ? x + 4 : x--; // ok, let's wrap args#define ADD_ONE(x) (x) + 1ADD_ONE(var) * 5 // results in(x) + 1 * 5// solution:#define ADD_ONE(x) ((x) + 1)Valery Lesin. C++ In-Depth, 20147требование ';' после макроса1.2.3.4.5.6.7.8.9.10.11.12.13.14.#define SWAP(x, y) x ^= y; y ^= x; x ^= y;if (a > b)SWAP(x, y); // oops!#define SWAP(x, y) { x ^= y; y ^= x; x ^= y; }if (a > b)SWAP(a, b); // compilation errorelse//...// solution, requires ';' in the end#define SWAP(a, b) do { x ^= y; y ^= x; x ^= y; } while(0)Valery Lesin.
C++ In-Depth, 20148Multiline macro• Нужны исключительно для облегчения чтения кода1.2.3.4.5.6.7.8.9.10.#define Verify(expr)do{ if (!(expr)){std::stringstream ss;ss << "Verification failed: " << #expr << " at \""<< BOOST_CURRENT_FUNCTION << "\" in " <<__FILE__ << ":" << __LINE__;LogError(ss.str());throw verify_error(ss.str());} } while (0, 0)Valery Lesin. C++ In-Depth, 2014\\\\\\\\\9Predefined defines• __LINE__ номер текущей строки• __FILE__ название текущего файла• __FUNCTION__ (или BOOST_CURRENT_FUNCTION)название функции• __linux__ WIN32 и т.д.
- настройка платформы• __COUNTER__ самоинкрементирующаяся константа1.2.3.4.5.6.7.8.9.10.11.12.#define CONCAT_IMPL(x, y) x##y#define MACRO_CONCAT(x,y) CONCAT_IMPL(x,y)#define LOCK(name) \scoped_lock MACRO_CONCAT(lock, __COUNTER__);void foo(){lock(mutex)// ...lock(mutex)// ...}Valery Lesin. C++ In-Depth, 201410assert1.2.3.4.5.6.7.8.9.10.11.12.13.14.15.16.17.18.19.20.21.22.#ifdef NDEBUG#define Assert(expr)\do\{\if (0, 0)\{\(void)(expr);\}\} while (0, 0)\#else\#define Assert(expr)\do{\if (!(expr))\{\std::stringstream ss;\ss << "Assertion failed: " << #expr << " at \""\<< BOOST_CURRENT_FUNCTION << "\" in " <<\__FILE__ << ":" << __LINE__;\AssertLogError(ss.str());\assert(expr);\} } while (0, 0)#endif // NDEBUGValery Lesin.
C++ In-Depth, 201411Вариативный макрос• Макросы не понимают шаблоны. Запятая,отделяющие параметры шаблонывоспринимается как отделение параметровмакроса.• Вариативный макрос не позволяет перебратьпараметры, только отдать дальше все их вместе1.2.3.4.5.6.7.8.// invocation with 2 argumentsPROCESS(map<int, double>)#define REFL_STRUCT_BODY(...)\void reflect(processor& proc, __VA_ARGS__ const& object)\{\typedef __VA_ARGS__ type;\//...Valery Lesin. C++ In-Depth, 201412Вопросы?Valery Lesin. C++ In-Depth, 201413.
Характеристики
Тип файла PDF
PDF-формат наиболее широко используется для просмотра любого типа файлов на любом устройстве. В него можно сохранить документ, таблицы, презентацию, текст, чертежи, вычисления, графики и всё остальное, что можно показать на экране любого устройства. Именно его лучше всего использовать для печати.
Например, если Вам нужно распечатать чертёж из автокада, Вы сохраните чертёж на флешку, но будет ли автокад в пункте печати? А если будет, то нужная версия с нужными библиотеками? Именно для этого и нужен формат PDF - в нём точно будет показано верно вне зависимости от того, в какой программе создали PDF-файл и есть ли нужная программа для его просмотра.