Как мне показать значение #define во время компиляции? - PullRequest
106 голосов
/ 13 октября 2009

Я пытаюсь выяснить, какую версию Boost использует мой код. Я хочу сделать что-то вроде этого:

#error BOOST_VERSION

но препроцессор не раскрывает BOOST_VERSION.

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

Ответы [ 13 ]

110 голосов
/ 19 апреля 2012

BOOST_PP_STRINGIZE кажется отличным решением для C ++, но не для обычного C.

Вот мое решение для GNU CPP:

/* Some test definition here */
#define DEFINED_BUT_NO_VALUE
#define DEFINED_INT 3
#define DEFINED_STR "ABC"

/* definition to expand macro then apply to pragma message */
#define VALUE_TO_STRING(x) #x
#define VALUE(x) VALUE_TO_STRING(x)
#define VAR_NAME_VALUE(var) #var "="  VALUE(var)

/* Some example here */
#pragma message(VAR_NAME_VALUE(NOT_DEFINED))
#pragma message(VAR_NAME_VALUE(DEFINED_BUT_NO_VALUE))
#pragma message(VAR_NAME_VALUE(DEFINED_INT))
#pragma message(VAR_NAME_VALUE(DEFINED_STR))

Приведенные выше определения приводят к:

test.c:10:9: note: #pragma message: NOT_DEFINED=NOT_DEFINED
test.c:11:9: note: #pragma message: DEFINED_BUT_NO_VALUE=
test.c:12:9: note: #pragma message: DEFINED_INT=3
test.c:13:9: note: #pragma message: DEFINED_STR="ABC"

Для "определено как целое число" , "определено как строка" , и "определено, но без значения" переменные, они работают просто отлично. Только для «не определено» переменной они отображаются точно так же, как и исходное имя переменной. Вы должны привыкнуть к этому - или, может быть, кто-то может предложить лучшее решение.

88 голосов
/ 29 мая 2012

Я знаю, что это долго после исходного запроса, но это все еще может быть полезно.

Это можно сделать в GCC с помощью оператора stringify "#", но это требует двух этапов.

#define XSTR(x) STR(x)
#define STR(x) #x

Значение макроса может затем отображаться с помощью:

#pragma message "The value of ABC: " XSTR(ABC)

См .: 3.4 Стрификация в онлайн-документации gcc.

55 голосов
/ 13 октября 2009

Если вы используете Visual C ++, вы можете использовать #pragma message:

#include <boost/preprocessor/stringize.hpp>
#pragma message("BOOST_VERSION=" BOOST_PP_STRINGIZE(BOOST_VERSION))

Редактировать: Спасибо LB за ссылку

По-видимому, эквивалент GCC (не тестировался):

#pragma message "BOOST_VERSION=" BOOST_PP_STRINGIZE(BOOST_VERSION)
12 голосов
/ 13 октября 2009

Насколько я знаю, "#error" будет печатать только строки, на самом деле вам даже не нужно использовать кавычки .

Вы пытались писать различные целенаправленно некорректные коды, используя "BOOST_VERSION"? Возможно, что-то вроде "blah [BOOST_VERSION] = foo;" скажет вам что-то вроде «строковый литерал 1.2.1 не может использоваться в качестве адреса массива». Это не будет красивое сообщение об ошибке, но, по крайней мере, оно покажет вам соответствующее значение. Вы можете поиграть, пока не найдете ошибку компиляции, которая сообщит вам значение.

10 голосов
/ 05 марта 2018

без повышения:

  1. снова определите тот же макрос, и компилятор HIMSELF выдаст предупреждение.

  2. Из предупреждения вы можете увидеть местоположение предыдущего определения.

  3. vi файл предыдущего определения.

ambarish@axiom:~/cpp$ g++ shiftOper.cpp
shiftOper.cpp:7:1: warning: "LINUX_VERSION_CODE" redefined
shiftOper.cpp:6:1: warning: this is the location of the previous definition

#define LINUX_VERSION_CODE 265216
#define LINUX_VERSION_CODE 666

int main ()
{

}
5 голосов
/ 28 января 2018
#define a <::BOOST_VERSION>
#include a
MSVC2015 : фатальная ошибка C1083: не удается открыть включаемый файл: ':: 106200': такого файла или каталога нет

Работает, даже если preprocess to file включено, даже если присутствуют недействительные токены:

#define a <::'*/`#>
#include a
MSVC2015 : фатальная ошибка C1083: Невозможно открыть включаемый файл: '::' * / `# ': такого файла или каталога нет
GCC4.x : предупреждение: отсутствует завершающий символ '[-Winvalid-pp-token]
#define a <:: '* / `#>
3 голосов
/ 27 ноября 2018

В Microsoft C / C ++ вы можете использовать встроенную _CRT_STRINGIZE() для печати констант. Многие из моих stdafx.h файлов содержат некоторую комбинацию из них:

#pragma message("_MSC_VER      is " _CRT_STRINGIZE(_MSC_VER))
#pragma message("_MFC_VER      is " _CRT_STRINGIZE(_MFC_VER))
#pragma message("_ATL_VER      is " _CRT_STRINGIZE(_ATL_VER))
#pragma message("WINVER        is " _CRT_STRINGIZE(WINVER))
#pragma message("_WIN32_WINNT  is " _CRT_STRINGIZE(_WIN32_WINNT))
#pragma message("_WIN32_IE     is " _CRT_STRINGIZE(_WIN32_IE))
#pragma message("NTDDI_VERSION is " _CRT_STRINGIZE(NTDDI_VERSION)) 

и выводит что-то вроде этого:

_MSC_VER      is 1915
_MFC_VER      is 0x0E00
_ATL_VER      is 0x0E00
WINVER        is 0x0600
_WIN32_WINNT  is 0x0600
_WIN32_IE     is 0x0700
NTDDI_VERSION is 0x06000000
3 голосов
/ 13 октября 2009

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

2 голосов
/ 13 октября 2009

Просмотр вывода препроцессора является наиболее близким к ответу, который вы запрашиваете.

Я знаю, что вы исключили это (и другие способы), но я не уверен, почему. У вас есть достаточно конкретная проблема, которую нужно решить, но вы не объяснили, почему какой-либо из «нормальных» методов не работает для вас.

2 голосов
/ 13 октября 2009

Вы ищете

#if BOOST_VERSION != "1.2"
#error "Bad version"
#endif

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

...