c++cmetaprogrammingpreprocessor

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


For some base. Base 1 even. Some sort of complex substitution -ing.

Also, and of course, doing this is not a good idea in real life production code.


Solution

  • You can relatively easy write a macro which adds two integers in binary. For example, a 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.

    I have changed formating of results and more importantly, I've added an overflow check.