简体   繁体   中英

How do i make preprocessor macros evaluate code before compilation

i'm using macros to define static size for some arrays in my code, i have defined a config macro variable at the top of my code and some macro variables depend on said macro variable. i can make a function that takes that value and returns the required size of the array but that would execute in runtime and i'll need to use VLAs. example below shows macro for SIZE of a number (with no repeating digits) and whether that number can begin with a zero ("0123" vs "1234").

code to calculate LIMIT in runtime:

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

i manually calculated the amount of said numbers for all values. is there a work around?

#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

The workaround could be to generate C code from something else.

Consider learning more, using GPP or your own C code generator (perhaps using GNU bison and in some simple cases GNU gawk or GNU autoconf ).

Observe that on Linux or POSIX, you could generate C code, compile it as a plugin, and dlopen(3) that plugin. For a useless example, see manydl.c . For useful (but obsolete) example, see my old GCC MELT .

Another approach ( GCC specific) might be to extend your compiler with GCC plugins . See bismon .

You can also generate machine code (in your program) using GNU lightning or (in C++) asmjit . Then read the Dragon book and this answer.

Read some books by Jacques Pitrat explaining that metaprogramming approach (reused in RefPerSys )

The concepts related to partial evaluation are relevant.

It's this some kind of the factorial?

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

You can use this in the loop expression in a macro or an inline function and the optimizing compiler will compute it at compile time.

#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))

If you wish you may define a precomputed array and use

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM