C预处理器宏是否可以包含预处理程序指令?

我想做相同的以下内容:

#define print_max(TYPE) \ # ifdef TYPE##_MAX \ printf("%lld\n", TYPE##_MAX); \ # endif print_max(INT); 

现在,只要我在函数宏中看到,就不允许使用#ifdef或任何嵌套的预处理器指令。 有任何想法吗?

更新:所以看起来这是不可能的。 即使是在运行时检查的黑客也无法实现。 所以我想我会选择以下内容:

 #ifndef BLAH_MAX # define BLAH_MAX 0 #endif # etc... for each type I'm interested in #define print_max(TYPE) \ if (TYPE##_MAX) \ printf("%lld\n", TYPE##_MAX); print_max(INT); print_max(BLAH); 

Boost预处理器 (适用于C和C ++,即使Boost作为一个整体是C ++库)可以帮助完成这类任务。 它不是在宏中使用#ifdef(不允许),而是帮助您多次包含文件,每次都定义不同的宏,以便文件可以使用#ifdef。

如果保存到max.c,下面的代码应该对文件顶部的MAXES #define中列出的每个单词执行所需的操作。 但是,如果任何_MAX值都是浮点数,它将无法工作,因为预处理器无法处理浮点数。

(Boost处理器是一个方便的工具,但它并不简单;你可以决定这种方法是否比复制和粘贴更好。)

 #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  #include  #include  /* 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 

我之前尝试过。 问题是#已被保留用于对宏参数进行字符串化。 它不会被解析为#define中的预处理器令牌。

我唯一的解决方案是作弊 – 生成一个类型列表,其中_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 

我不认为这是##运算符不被#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 TYPE)。 问题是#ifdef只接受#defined符号,而不接受#define参数。 这是两件不同的事情。

与模板不同,预处理器不是图灵完备的 。 宏中的#ifdef是不可能的。 您唯一的解决方案是确保只在具有匹配_MAX定义的类型(例如INT_MAX上调用print_max 。 编译器肯定会告诉你它们何时不是。

没有简单的方法可以做到这一点。 你最接近的是#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); 

只要您只对积分值感兴趣,并假设硬件使用2的恭维和8位字节:

 // Of course all this MAX/MIN stuff assumes 2's compilment, with 8-bit bytes... #define LARGEST_INTEGRAL_TYPE long long /* This will evaluate to TRUE for an unsigned type, and FALSE for a signed * type. We use 'signed char' since it should be the smallest signed type * (which will sign-extend up to 's size) vs. possibly overflowing if * going in the other direction (from a larger type to a smaller one). */ #define ISUNSIGNED(type) (((type) ((signed char) -1)) > (type) 0) /* We must test for the "signed-ness" of  to determine how to calculate * the minimum/maximum value. * * eg, If a typedef'ed type name is passed in that is actually an unsigned * type: * * typedef unsigned int Oid; * MAXIMUM_(Oid); */ #define MINIMUM_(type) ((type) (ISUNSIGNED(type) ? MINIMUM_UNSIGNED_(type) \ : MINIMUM_SIGNED_( type))) #define MAXIMUM_(type) ((type) (ISUNSIGNED(type) ? MAXIMUM_UNSIGNED_(type) \ : MAXIMUM_SIGNED_( type))) /* Minumum unsigned value; zero, by definition -- we really only have this * macro for symmetry. */ #define MINIMUM_UNSIGNED_(type) ((type) 0) // Maximum unsigned value; all 1's. #define MAXIMUM_UNSIGNED_(type) \ ((~((unsigned LARGEST_INTEGRAL_TYPE) 0)) \ >> ((sizeof(LARGEST_INTEGRAL_TYPE) - sizeof(type)) * 8)) /* Minimum signed value; a 1 in the most-significant bit. * * We use LARGEST_INTEGRAL_TYPE as our base type for the initial bit-shift * because we should never overflow (ie,  should always be the same * size or smaller than LARGEST_INTEGRAL_TYPE). */ #define MINIMUM_SIGNED_(type) \ ((type) \ ((signed LARGEST_INTEGRAL_TYPE) \ (~((unsigned LARGEST_INTEGRAL_TYPE) 0x0) << ((sizeof(type) * 8) - 1)))) // Maximum signed value; 0 in most-significant bit; remaining bits all 1's. #define MAXIMUM_SIGNED_(type) (~MINIMUM_SIGNED_(type))