Можно ли вывести переменную из заголовочного файла? - PullRequest
1 голос
/ 09 мая 2019

Предположим, у меня есть файл заголовка с такими строками:

#if LONG_BIT != 8 * SIZEOF_LONG
/* 04-Oct-2000 LONG_BIT is apparently (mis)defined as 64 on some recent
 * 32-bit platforms using gcc.  We try to catch that here at compile-time
 * rather than waiting for integer multiplication to trigger bogus
 * overflows.
 */
#error "pp897:  LONG_BIT  definition appears wrong for platform (bad gcc/glibc config?)."
#endif

Я хотел бы вывести значения LONG_BIT и SIZEOF_LONG. Возможно ли это сделать или это невозможно из заголовочного файла?

Ответы [ 3 ]

3 голосов
/ 09 мая 2019

_Static_assert в C или static_assert в C ++ могут проверять условия и отображать строку, и строка может быть построена с расширениями препроцессора:

#define LONG_BIT    64
#define SIZEOF_LONG 4

#define StringizeHelper(x)  #x
#define Stringize(x)        StringizeHelper(x)

_Static_assert(LONG_BIT == 8 * SIZEOF_LONG,
    "LONG_BIT is " Stringize(LONG_BIT) " but must be 8 * "
    Stringize(SIZEOF_LONG) ".");

Выход с лязгом:

x.c:7:1: error: static_assert failed "LONG_BIT is 64 but must be 8 * 4."
_Static_assert(LONG_BIT == 8 * SIZEOF_LONG,
^              ~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
1 голос
/ 09 мая 2019

У вас есть несколько значений для проверки в этом случае. Вы можете проверить правдоподобные из них один за другим, как оператор switch / case, по умолчанию на всякий случай.

Автономный пример. 2 первых define утверждения здесь для теста, удалите из окончательного кода

// completely bogus/incoherent values just to test
#define LONG_BIT 32
#define SIZEOF_LONG 4444

// operational test from now on    
#if LONG_BIT != 8 * SIZEOF_LONG
#if LONG_BIT == 32
#error "pp897:  LONG_BIT  definition appears wrong for platform (bad gcc/glibc config?): size 32"
#elif LONG_BIT == 64
#error "pp897:  LONG_BIT  definition appears wrong for platform (bad gcc/glibc config?): size 64"
#else
#error "pp897:  LONG_BIT  definition appears wrong for platform (bad gcc/glibc config?): size ???"
#endif
#endif

вывод компиляции:

test.c:7:2: error: #error "pp897:  LONG_BIT  definition appears wrong for platfo
rm (bad gcc/glibc config?): size 32"

Этот метод совместим со всеми стандартами, включая C89

0 голосов
/ 10 мая 2019

С GCC или Clang (по крайней мере) вы можете распечатать значения макросов препроцессора:

#define LONG_BIT 60
#pragma message "LONG_BIT is " STRINGIFY(LONG_BIT)

Но это не даст вам значение sizeof(long), которое не является препроцессоромпостроить.Это также не будет делать арифметику;LONG_BIT должно быть действительным числом, чтобы получить желаемое сообщение.

Это не работает с #error, который не выполняет подстановку макросов в тексте.

Здесь STRINGIFY имеет обычное двухэтапное определение:

#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)

Вы также можете написать целое сообщение внутри аргументов, по крайней мере, в этом случае, но следите за неожиданными расширениями:

#pragma message STRINGIFY(LONG BIT is LONG_BIT)
...