提问人:pixelbeat 提问时间:11/19/2008 最后编辑:hopperpixelbeat 更新时间:8/18/2018 访问量:39815
C 预处理器宏是否可以包含预处理器指令?
Is it possible for C preprocessor macros to contain preprocessor directives?
问:
我想做以下等效的事情:
#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);
答:
我不认为这是 ## 运算符在 #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 参数。这是两件不同的事情。
我以前试过。问题是已经保留了用于字符串化宏参数。它不会像 define 中的令牌那样解析为预处理器令牌。#
#
评论
与模板不同,预处理器不是图灵完备的。宏内部是不可能的。唯一的解决方案是确保只调用定义了匹配的类型,例如 .编译器肯定会告诉你什么时候不是。#ifdef
print_max
_MAX
INT_MAX
我唯一的解决方案是作弊 - 生成一个将_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
Boost 预处理器(适用于 C 和 C++,即使 Boost 作为一个整体是一个 C++ 库)库可以帮助完成此类任务。它不是在宏中使用 #ifdef(这是不允许的),而是可以帮助您多次包含一个文件,每次都定义不同的宏,以便文件可以使用 #ifdef。
如果将以下代码保存到 max.c,则应该对文件顶部的 MAXES #define 中列出的每个单词执行所需的操作。但是,如果任何_MAX值是浮点数,则它不起作用,因为预处理器无法处理浮点数。
(Boost Processor 是一个方便的工具,但它并不完全简单;您可以决定这种方法是否是对复制和粘贴的改进。
#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
没有简单的方法可以做到这一点。最接近的是 #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”中是有道理的,您可以在需要时将其包含在内。您甚至可以编写一个脚本,从 “感兴趣的宏”列表
然后,您的代码变为
#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 <type>'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 <type> to determine how to calculate
* the minimum/maximum value.
*
* e.g., 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 (i.e., <type> 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))
上一个:你能在C++中保护嵌套类吗?
下一个:使用存储过程参数的嵌套数据列表
评论