代码之家  ›  专栏  ›  技术社区  ›  pixelbeat

C预处理器宏是否可能包含预处理器指令?

  •  28
  • pixelbeat  · 技术社区  · 16 年前

    #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);
    
    7 回复  |  直到 11 年前
        1
  •  13
  •   Josh Kelley    16 年前

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

    下面的代码如果保存到max.c,应该可以为文件顶部的MAXES#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
    
        2
  •  6
  •   Johannes Schaub - litb    16 年前

    我以前试过。问题是 # # 定义

        3
  •  4
  •   user3458 user3458    16 年前

    我唯一的解决办法就是作弊——生成一个类型列表,其中有一个_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
  •  0
  •   Ferruccio    16 年前

    我不认为在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)
    }
    

        5
  •  0
  •   Andreas Magnusson    16 年前

    与模板不同,预处理器不是 turing-complete . 一 #ifdef 在宏内部是不可能的。你唯一的解决办法就是确保你只打电话 print_max 在具有匹配 _MAX INT_MAX . 编译器肯定会告诉您它们何时不存在。

        6
  •  0
  •   Chris Dodd    15 年前

    没有简单的方法可以做到这一点。最接近的方法是#定义大量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);
    
        7
  •  0
  •   Gary H    6 年前

    只要您只对整数值感兴趣,并且假设硬件使用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))