Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way to get the C precompiler to use a mathematical result when concatenating symbols?

I have a C macro that concatenates bits together in order to resolve to other macros. I'll demonstrate using an admittedly pointless macro called MULT which multiplies two numbers. So long as I pass in an actual literal integer to its first parameter it works. But passing in a mathematical expression triggers an error.

For example:

#define MULT_2(X) X+X
#define MULT_3(X) X+X+X
#define MULT_4(X) X+X+X+X

#define EXPAND_(A) A
#define MULT__(N, X) EXPAND_(MULT_ ## N)(X)
#define MULT_(N, X) MULT__(N, X)
#define MULT(N, X) MULT_(EXPAND_(N), X)

int main() {
    int num;

    // This works:
    num = MULT(4, 1);
    printf("num: %d\n", num);

    // This does not:
    num = MULT(2+2, 1);
    printf("num: %d\n", num);

    return 0;
}

(To be honest, I don't fully understand why getting this macro to work with just a literal integer requires three extra macros, MULT_, MULT__, and EXPAND_. But regardless...)

Is there anyway to rewrite this so that passing in an expression like 2+2 or 1 * 4 or 1 << 2 to its first argument will actually work?

I'm curious about the answer mainly to broaden my knowledge of C and its preprocessor. But I'm also hoping to make use of this for a project that's being written in C89, which means no variadic macros, so if there's a solution that avoids using those, I'd love to see it!

like image 600
Bri Bri Avatar asked Jan 22 '26 12:01

Bri Bri


1 Answers

Is there any way to get the C precompiler to use a mathematical result when concatenating symbols?

Yes, but you have to make the arithmetic in preprocessor, not outside of it, and then use that computed result by preprocessor to do the operation. It would look something along:

#include <stdio.h>

#define ADD_1_1  2
#define ADD_1_2  3
#define ADD_2_2  4
/* etc, bilions of combinations */
#define ADD(a, b)  ADD_##a##_##b

#define MULT_2(X) X+X
#define MULT_3(X) X+X+X
#define MULT_4(X) X+X+X+X

#define EXPAND_(A) A
#define MULT__(N, X) EXPAND_(MULT_ ## N)(X)
#define MULT_(N, X) MULT__(N, X)
#define MULT(N, X) MULT_(EXPAND_(N), X)

int main() {
    int num;
    num = MULT(4, 1);
    printf("num: %d\n", num);
    num = MULT(ADD(2, 2), 1);
    printf("num: %d\n", num);
}

You might be interested in boost library BOOST_PP_ADD and BOOST_PP_MUL and P99 library P99_ADD and P99_MUL (use boost).

like image 125
KamilCuk Avatar answered Jan 25 '26 19:01

KamilCuk



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!