Schim
Schim

Reputation: 401

Can the C preprocessor perform integer arithmetic?

Is the C preprocessor able to perform integer arithmetic?

E.g.:

#define PI 3.1416
#define OP PI/100
#define OP2 PI%100

Is there a way OP and/or OP2 get calculated in the preprocessing phase?

Upvotes: 39

Views: 84941

Answers (6)

radoslav006
radoslav006

Reputation: 125

One can achieve something like preprocessor arithmetic by usage of conditional defines. The output value should be conditionally defined for every (possible/supported) value of input(s). Such a list of defines can be of course generated to make life easier, and here is a simple example:

File static_log2.h

#if STATIC_LOG2_ARG & (1 << 31)
#define STATIC_LOG2_VALUE 31
 
#elif STATIC_LOG2_ARG & (1 << 30)
#define STATIC_LOG2_VALUE 30
 
/* Other values here */

#elif STATIC_LOG2_ARG & (1 << 1)
#define STATIC_LOG2_VALUE 0
 
#else
#error "Invalid STATIC_LOG2_ARG value."
#endif

And the usage will be like:

File test.c

#define STATIC_LOG2_ARG 89
#include static_log2.h
char myarray[STATIC_LOG2_VALUE]; // sizeof(myarray) == 6

It looks as it looks, and I consider it as an interesting fact rather than good practice. Probably this could be done in a more elegant way, but you get the idea.

It is based on Ralf Holly's article: Using the C preprocessor to perform compile-time computations

Upvotes: 0

Steve Jessop
Steve Jessop

Reputation: 279245

Integer arithmetic? Run the following program to find out:

#include "stdio.h"
int main() {
    #if 1 + 1 == 2
        printf("1+1==2\n");
    #endif
    #if 1 + 1 == 3
        printf("1+1==3\n");
    #endif
}

The answer is "yes". There is a way to make the preprocessor perform integer arithmetic, which is to use it in a preprocessor condition.

Note however that your examples are not integer arithmetic. I just checked, and GCC's preprocessor fails if you try to make it do float comparisons. I haven't checked whether the standard ever allows floating point arithmetic in the preprocessor.

Regular macro expansion does not evaluate integer expressions. It leaves it to the compiler, as can be seen by preprocessing (-E in GCC) the following:

#define ONEPLUSONE (1 + 1)
#if ONEPLUSONE == 2
   int i = ONEPLUSONE;
#endif

The result is int i = (1 + 1); (plus probably some stuff to indicate source file names and line numbers and such).

Upvotes: 45

Phil
Phil

Reputation: 420

Be careful when doing arithmetic: add parentheses.

#define SIZE4 4
#define SIZE8 8
#define TOTALSIZE SIZE4 + SIZE8

If you ever use something like:

unsigned int i = TOTALSIZE/4;

And expect i to be 3. You would get 4 + 2 = 6 instead.

Add parentheses:

#define TOTALSIZE (SIZE4 + SIZE8)

Upvotes: 7

highBandWidth
highBandWidth

Reputation: 17321

Yes, it can be done with the Boost Preprocessor. And it is compatible with pure C, so you can use it in C programs with C-only compilations. Your code involves floating-point numbers though, so I think that needs to be done indirectly.

#include <boost/preprocessor/arithmetic/div.hpp>
BOOST_PP_DIV(11, 5) // expands to 2
#define KB 1024
#define HKB BOOST_PP_DIV(A,2)
#define REM(A,B) BOOST_PP_SUB(A, BOOST_PP_MUL(B, BOOST_PP_DIV(A,B)))
#define RKB REM(KB,2)

int div = HKB;
int rem = RKB;

This preprocesses to (check with gcc -S):

int div = 512;
int rem = 0;

Thanks to this question.

Upvotes: 9

Stephen Canon
Stephen Canon

Reputation: 106127

Yes.

I can't believe that no one has yet linked to a certain obfuscated C contest winner. The guy implemented an ALU in the preprocessor via recursive includes. Here is the implementation, and here is something of an explanation.

Now, that said, you don't want to do what that guy did. It's fun and all, but look at the compile times in his hint file (not to mention the fact that the resulting code is unmaintainable). More commonly, people use the pre-processor strictly for text replacement, and evaluation of constant integer arithmetic happens either at compile time or run time.

As others noted however, you can do some arithmetic in #if statements.

Upvotes: 7

shoosh
shoosh

Reputation: 78914

The code you wrote doesn't actually make the preprocessor do any calculation. A #define does simple text replacement, so with this defined:

#define PI 3.1416
#define OP PI/100

This code:

if (OP == x) { ... }

becomes

if (3.1416/100 == x) { ... }

and then it gets compiled. The compiler in turn may choose to take such an expression and calculate it at compile time and produce a code equivalent to this:

if (0.031416 == x) { ... }

But this is the compiler, not the preprocessor.

To answer your question, yes, the preprocessor CAN do some arithmetic. This can be seen when you write something like this:

#if (3.141/100 == 20)
   printf("yo");
#elif (3+3 == 6)
   printf("hey");
#endif

Upvotes: 22

Related Questions