В тех случаях, когда в отладочной версии не хватает стандартных инструментов (TRACE/ATLTRACE, assert/ASSERT/ATLASSERT), приходится писать блоки кода в обрамлении
#ifdef _DEBUG
...
#endif
что не добавляет красоты, но потенциально плодит ошибки (компилятору абсолютно пофиг, где стоит #endif).
Макросы IS_DEBUG и DEBUG_ONLY позволяют свести эти изыски к синтаксису языка Си.
// IS_DEBUG - булева константа, истинна если собирается DEBUG-версия
#ifndef IS_DEBUG
#if defined(DEBUG) || defined(_DEBUG) // проверяем оба признака
#define IS_DEBUG true
#else
#define IS_DEBUG false
#endif
#endif
// DEBUG_ONLY - префикс оператора, который выполнится только в DEBUG-версии
// синтаксис - аналогичен составному оператору while()
#ifndef DEBUG_ONLY
#define DEBUG_ONLY if(!(IS_DEBUG)) {} else
// такая конструкция нужна, чтобы не конфликтовать с внешним if
#endif
// аналогично ему - RELEASE_ONLY
// хотя зачем он может пригодиться - не знаю; пусть будет.
#ifndef RELEASE_ONLY
#define RELEASE_ONLY if(IS_DEBUG) {} else
#endif
Пример использования
// одиночный оператор
DEBUG_ONLY fprintf(log, "Контрольная точка 1.\n");
// составной оператор
DEBUG_ONLY
{
FILE* log = fopen("c:/log.txt", "a");
fprintf(log, "Контрольная точка 2.\n");
fclose(log);
}
// использование в выражениях
printf("Вас приветствует CoolApp (ver.1.2.%s)\n", IS_DEBUG ? "beta" : "rc1");
int i = (!IS_DEBUG) * rand(); // в дебаге - всегда 0, в релизе - случайное число