Для макросов препроцессора C действительно ли возможно содержать директивы препроцессору?

31
задан hopper 8 August 2013 в 14:22
поделиться

6 ответов

Препроцессор Повышения (который работает на C, а также C++, даже при том, что Повышение в целом является библиотекой C++) библиотека может помочь с этим видом задачи. Вместо того, чтобы использовать #ifdef в рамках макроса (который не разрешен), это помогает Вам включать файл многократно с различными макросами, определенными каждый раз, так, чтобы файл мог использовать #ifdef.

следующий код, если сохранено к max.c, должен сделать то, что Вы хотите для каждого из слов, перечисленных в МАКСАХ #define наверху файла. Однако это не будет работать, если какое-либо из значений _MAX будет плавающей точкой, так как препроцессор не может обработать плавающую точку.

(Процессор повышения является удобным инструментом, но это не точно просто; можно решить, является ли этот подход улучшением по сравнению с копией-и-вставкой.)

#define MAXES (SHRT)(INT)(LONG)(PATH)(DOESNT_EXIST)

#if !BOOST_PP_IS_ITERATING

/* This portion of the file (from here to #else) is the "main" file */

#include <values.h>
#include <stdio.h>
#include <boost/preprocessor.hpp>

/* Define a function print_maxes that iterates over the bottom portion of this
 * file for each word in MAXES */
#define BOOST_PP_FILENAME_1 "max.c"
#define BOOST_PP_ITERATION_LIMITS (0,BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(MAXES)))
void print_maxes(void) {
#include BOOST_PP_ITERATE()
}

int main(int argc, char *argv[])
{
    print_maxes();
}

#else

/* This portion of the file is evaluated multiple times, with
 * BOOST_PP_ITERATION() resolving to a different number every time */

/* Use BOOST_PP_ITERATION() to look up the current word in MAXES */
#define CURRENT BOOST_PP_SEQ_ELEM(BOOST_PP_ITERATION(), MAXES)
#define CURRENT_MAX BOOST_PP_CAT(CURRENT, _MAX)

#if CURRENT_MAX
printf("The max of " BOOST_PP_STRINGIZE(CURRENT) " is %lld\n", (long long) CURRENT_MAX);
#else
printf("The max of " BOOST_PP_STRINGIZE(CURRENT) " is undefined\n");
#endif

#undef CURRENT
#undef CURRENT_MAX

#endif
13
ответ дан Josh Kelley 27 November 2019 в 22:49
поделиться

Я попробовал это прежде. Проблема состоит в том, что # уже резервируется к stringize макро-параметр. Это не анализируется, поскольку маркер препроцессора как тот в # определяет.

6
ответ дан Johannes Schaub - litb 27 November 2019 в 22:49
поделиться

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

#define PRINT_MAX(type) printf("%lld\n", _TYPE##_MAX);
#define HAVE_MAX(type) _TYPE##_MAX // not sure if this works 


/* a repetitious block of code that I cannot factor out - this is the cheat */
#ifdef HAVE_MAX(INT)
#define PRINT_INT_MAX PRINT_MAX(INT)
#endif

#ifdef HAVE_MAX(LONG)
#define PRINT_LONG_MAX PRINT_MAX(LONG)
#endif
/* end of cheat */


#define print_max(type) PRINT_##TYPE##_MAX
4
ответ дан 27 November 2019 в 22:49
поделиться

Я не думаю, что это - случай ## оператора, не позволяемого в #ifdef. Я попробовал это:

#define _print_max(TYPE) \
#ifdef TYPE \
printf("%lld\n", _TYPE); \
#endif

#define print_max(TYPE) _print_max(MAX##_TYPE)


void main() 
{
    print_max(INT)
}

и это все еще не работало (этому не нравился ТИП #ifdef). Проблема состоит в том, что #ifdef только примет #defined символы, не #define аргументы. Те - две разных вещи.

0
ответ дан Ferruccio 27 November 2019 в 22:49
поделиться

В отличие от шаблонов, препроцессор не полон Тьюрингом . #ifdef внутренняя часть макрос не возможен. Ваше единственное решение состоит в том, чтобы удостовериться, что Вы только звоните print_max на типах, который имеет соответствие _MAX определенный, например, INT_MAX. Компилятор, конечно, скажет Вам, когда они не будут.

0
ответ дан Andreas Magnusson 27 November 2019 в 22:49
поделиться

Нет простого способа сделать это. Самое близкое, что вы можете сделать, - это #define большое количество макросов IFDEF, таких как:

#undef IFDEF_INT_MAX
#ifdef INT_MAX
#define IFDEF_INT_MAX(X)  X
#else
#define IFDEF_INT_MAX(X)
#endif

#undef IFDEF_BLAH_MAX
#ifdef BLAH_MAX
#define IFDEF_BLAH_MAX(X)  X
#else
#define IFDEF_BLAH_MAX(X)
#endif

     :

, так как вам нужно много из них (и они могут быть полезны в нескольких местах), это дает много Имеет смысл поместить все это в отдельный файл заголовка ifdefs.h, который вы можете включить, когда вам это понадобится. Вы даже можете написать сценарий, который регенерирует ifdef.h из список «представляющих интерес макросов»

Затем ваш код станет

#include "ifdefs.h"
#define print_max(TYPE) \
IFDEF_##TYPE##_MAX( printf("%lld\n", TYPE##_MAX); )

print_max(INT);
print_max(BLAH);
0
ответ дан 27 November 2019 в 22:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: