我如何让预处理器宏在编译前评估代码

How do i make preprocessor macros evaluate code before compilation

我在我的代码中使用宏定义一些数组的静态大小,我在我的代码顶部定义了一个配置宏变量,一些宏变量依赖于所述宏变量。我可以制作一个函数,该函数采用该值和 returns 所需的数组大小,但它会在运行时执行,我需要使用 VLA。 下面的示例显示了一个数字大小的宏(没有重复数字)以及该数字是否可以以零开头(“0123”与“1234”)。

运行时计算 LIMIT 的代码:

int limit(int size, int npz){
    l = npz ? 9 : 10;
    for(int i = 1; i < size; i++)
        l *= 10 - i;
    return l;
}

我手动计算了所有值的所述数字的数量。有解决办法吗?

#define SIZE 4 // 1 .. 10
#define NO_PADDING_ZERO 1 // 1 | 0
#if NO_PADDING_ZERO
    #if SIZE == 1
        #define LIMIT 9
    #elif SIZE == 2
        #define LIMIT 81
    #elif SIZE == 3
        #define LIMIT 648
    #elif SIZE == 4
        #define LIMIT 4536
    #elif SIZE == 5
        #define LIMIT 27216
    #elif SIZE == 6
        #define LIMIT 136080
    #elif SIZE == 7
        #define LIMIT 544320
    #elif SIZE == 8
        #define LIMIT 1632960
    #else
        #define LIMIT 3265920
    #endif
#else
    #if SIZE == 1
        #define LIMIT 10
    #elif SIZE == 2
        #define LIMIT 90
    #elif SIZE == 3
        #define LIMIT 720
    #elif SIZE == 4
        #define LIMIT 5040
    #elif SIZE == 5
        #define LIMIT 30240
    #elif SIZE == 6
        #define LIMIT 151200
    #elif SIZE == 7
        #define LIMIT 604800
    #elif SIZE == 8
        #define LIMIT 1814400
    #else
        #define LIMIT 3628800
    #endif
#endif

解决方法是从其他东西生成 C 代码。

考虑学习更多,使用 GPP or your own C code generator (perhaps using GNU bison and in some simple cases GNU gawk or GNU autoconf)。

观察 Linux 或 POSIX,您可以生成 C 代码,将其编译为插件,并且 dlopen(3) that plugin. For a useless example, see manydl.c. For useful (but obsolete) example, see my old GCC MELT

另一种方法(GCC specific) might be to extend your compiler with GCC plugins. See bismon

您还可以使用 GNU lightning or (in C++) asmjit. Then read the Dragon book and this 答案生成机器代码(在您的程序中)。

阅读 Jacques Pitrat explaining that metaprogramming approach (reused in RefPerSys)

的一些书

partial evaluation相关的概念是相关的。

这是某种阶乘吗?

(10 - NO_PADDING_ZERO) * 9 * 8 * ... * (10 - LIMIT)

您可以在宏或内联函数的循环表达式中使用它,优化编译器将在编译时计算它。

#include <bool.h>

inline int limit(int size, bool npz){
    int l = 10 - npz;
    for(int i = 1; i < size; i++)
        l *= 10 - i;
    return l;
}

#define LIMIT (limit(SIZE, NO_PADDING_ZERO))

如果您愿意,可以定义一个预先计算的数组并使用

#define LIMIT (array[SIZE][NO_PADDING_ZERO])