Search code examples
cmacrospreprocessor

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

Solution

  • 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])