Can I add numbers with the C/C++ preprocessor? Can I add numbers with the C/C++ preprocessor? c c

Can I add numbers with the C/C++ preprocessor?


The preprocessor operates on preprocessing tokens and the only time that it evaluates numbers is during the evaluation of a #if or #elif directive. Other than that, numbers aren't really numbers during preprocessing; they are classified as preprocessing number tokens, which aren't actually numbers.

You could evaluate basic arithmetic using token concatenation:

#define ADD_0_0 0#define ADD_0_1 1#define ADD_1_0 1#define ADD_1_1 2#define ADD(x, y) ADD##_##x##_##yADD(1, 0) // expands to 1ADD(1, 1) // expands to 2

Really, though, there's no reason to do this, and it would be silly to do so (you'd have to define a huge number of macros for it to be even remotely useful).

It would be more sensible to have a macro that expands to an integral constant expression that can be evaluated by the compiler:

#define ADD(x, y) ((x) + (y))ADD(1, 1) // expands to ((1) + (1))

The compiler will be able to evaluate the 1 + 1 expression.


You can relatively easy write macro which adds two integers in binary. For example - macro which sums two 4-bit integers in binary :

#include "stdio.h"// XOR truth table#define XOR_0_0 0#define XOR_0_1 1#define XOR_1_0 1#define XOR_1_1 0// OR truth table#define OR_0_0 0#define OR_0_1 1#define OR_1_0 1#define OR_1_1 1// AND truth table#define AND_0_0 0#define AND_0_1 0#define AND_1_0 0#define AND_1_1 1// concatenation macros#define XOR_X(x,y) XOR_##x##_##y#define   OR_X(x,y) OR_##x##_##y#define  AND_X(x,y) AND_##x##_##y#define OVERFLOW_X(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) OVERFLOW_##rc1 (rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4)// stringification macros#define STR_X(x) #x#define STR(x) STR_X(x)// boolean operators#define XOR(x,y) XOR_X(x,y)#define   OR(x,y) OR_X(x,y)#define  AND(x,y) AND_X(x,y)// carry_bit + bit1 + bit2#define BIT_SUM(carry,bit1,bit2) XOR(carry, XOR(bit1,bit2))// carry_bit + carry_bit_of(bit1 + bit2)#define CARRY_SUM(carry,bit1,bit2) OR(carry, AND(bit1,bit2))// do we have overflow or maybe result perfectly fits into 4 bits ?#define OVERFLOW_0(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) SHOW_RESULT(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4)#define OVERFLOW_1(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) SHOW_OVERFLOW(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4)// draft-horse macros which performs addition of two 4-bit integers#define ADD_BIN_NUM(a1,a2,a3,a4, b1,b2,b3,b4) ADD_BIN_NUM_4(0,0,0,0, 0,0,0,0, a1,a2,a3,a4, b1,b2,b3,b4)#define ADD_BIN_NUM_4(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) ADD_BIN_NUM_3(rc1,rc2,rc3,AND(CARRY_SUM(0,a4,b4),OR(a4,b4)), rb1,rb2,rb3,BIT_SUM(0,a4,b4), a1,a2,a3,a4, b1,b2,b3,b4)#define ADD_BIN_NUM_3(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) ADD_BIN_NUM_2(rc1,rc2,AND(CARRY_SUM(rc4,a3,b3),OR(a3,b3)),rc4, rb1,rb2,BIT_SUM(rc4,a3,b3),rb4, a1,a2,a3,a4, b1,b2,b3,b4)#define ADD_BIN_NUM_2(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) ADD_BIN_NUM_1(rc1,AND(CARRY_SUM(rc3,a2,b2),OR(a2,b2)),rc3,rc4, rb1,BIT_SUM(rc3,a2,b2),rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4)#define ADD_BIN_NUM_1(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4)      OVERFLOW(AND(CARRY_SUM(rc2,a1,b1),OR(a1,b1)),rc2,rc3,rc4, BIT_SUM(rc2,a1,b1),rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4)#define OVERFLOW(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) OVERFLOW_X(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4)#define   SHOW_RESULT(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) STR(a1) STR(a2) STR(a3) STR(a4) " + " STR(b1) STR(b2) STR(b3) STR(b4) " = " STR(rb1) STR(rb2) STR(rb3) STR(rb4)#define   SHOW_OVERFLOW(rc1,rc2,rc3,rc4, rb1,rb2,rb3,rb4, a1,a2,a3,a4, b1,b2,b3,b4) STR(a1) STR(a2) STR(a3) STR(a4) " + " STR(b1) STR(b2) STR(b3) STR(b4) " = overflow"void main(){    printf("%s\n",         ADD_BIN_NUM(                    0,0,0,1, // first  4-bit int                    1,0,1,1) // second 4-bit int                    );    printf("%s\n",         ADD_BIN_NUM(                    0,1,0,0, // first  4-bit int                    0,1,0,1) // second 4-bit int                );    printf("%s\n",         ADD_BIN_NUM(                    1,0,1,1, // first  4-bit int                    0,1,1,0) // second 4-bit int                );}

This macro can be easily extended for addition of two 8-bit or 16-bit or even 32-bit ints.So basically all that we need is token concatenation and substitution rules to achieve amazing results with macros.

EDIT:I have changed formating of results and more importantly - I've added overflow check.

HTH!


It is quite possible to do bounded integer addition in the preprocessor. And, it is actually needed more often than one would really hope, i.e., the alternative to just have ((2) + (3)) in the program doesn't work. (E.g., you can't have a variable called x((2)+(3))). The idea is simple: turn the addition to increments, which you don't mind (too much) listing them all out. E.g.,

#define INC(x) INC_ ## x#define INC_0 1#define INC_1 2#define INC_2 3#define INC_3 4#define INC_4 5#define INC_5 6#define INC_6 7#define INC_7 8#define INC_8 9#define INC_9 10INC(7) // => 8

Now we know how to do addition to up to 1.

#define ADD(x, y) ADD_ ## x(y)#define ADD_0(x) x#define ADD_1(x) INC(x)ADD(0, 2) // => 2ADD(1, 2) // => 3

To add to even larger numbers, you need some sort of "recursion".

#define ADD_2(x) ADD_1(INC(x))#define ADD_3(x) ADD_2(INC(x))#define ADD_4(x) ADD_3(INC(x))#define ADD_5(x) ADD_4(INC(x))#define ADD_6(x) ADD_5(INC(x))#define ADD_7(x) ADD_6(INC(x))#define ADD_8(x) ADD_7(INC(x))#define ADD_9(x) ADD_8(INC(x))#define ADD_10(x) ADD_9(INC(x))ADD(5, 2) // => 7

One has to be careful in this, however. E.g., the following does not work.

#define ADD_2(x) INC(ADD_1(x))ADD(2, 2) // => INC_ADD_1(2)

For any extended use of such tricks, Boost Preprocessor is your friend.