tags:

views:

1203

answers:

8

Hi, as the questions says, is the C preprocessor able to do it?

E.g.:

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

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

Thanks.

A: 

D.I.Y to see true or false.

EffoStaff Effo
This isn't a very helpful answer - you won't gain reputation this way.
Jonathan Leffler
i encourage people "DIY" for such simplest things by writing just 8 or less lines code.
EffoStaff Effo
It only tells you if YOUR preprocessor can. Doesn't say anything about C preprocessors in general.
MSalters
did you see it in any C/C++ standard? share w/ me
EffoStaff Effo
+1  A: 

No, but why do you want to do that?

Any reasonable compiler should be able to optimize those constants away, and just calculate them at compile-time. The preprocessor is just a tool that works on the tokens of C source code, no more no less.

AraK
+1  A: 

Why not just using a calculator? Anyway, a macro should do the trick :)

machielo
This isn't a very helpful answer - you won't gain reputation this way.
Jonathan Leffler
I point at the use of a macro that calculates what he wants to calculate, and most compilers will do those calculations at compile time anyway ;)
machielo
+9  A: 

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
 }

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

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

Steve Jessop
Come on, onebyone. What goes at the end of every `main()` function?
Chris Lutz
Chris: We live in the future now, and while the flying cars are still missing, default return values from the main function have arrived!
Thomas Padron-McCarthy
@Chris: A close curly brace, reaching which "returns a value of 0" (5.1.2.2.3, Program Termination). If I'm not allowed to assume standard C in a question tagged "C", then what's the world coming to? Can't you find someone who is using //-style comments in code that might be seen by a C89 compiler, and complain about them instead? ;-)
Steve Jessop
@Chris -- The closing brace? :-)
Chris J
Oh noes, I've just realised what Chris must have meant! Because of the way SO formats code, my program *doesn't have a terminating newline*! This isn't even an invalid program which the compiler must diagnose, it's undefined behaviour. Horror, alarm, and general panic! I must fix it at once. `;-p`
Steve Jessop
Just to be clear, the preprocessor can do *integer* arithmetic, and is limited to using `long` (or `long` `long`) data values.
Loadmaster
That's what I suspected, but the evidence is that neither of us can be bothered to look up where in the C standard it forbids preprocessors to support floating point as an extension...
Steve Jessop
+6  A: 

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
shoosh
Sadly, if you try your conditional compilation snippet, you get the message from GCC: `x.c:5:6: error: floating constant in preprocessor expression`. You can do integer arithmetic with the C pre-processor; you cannot do floating point arithmetic with it.
Jonathan Leffler
+1  A: 

YES, I mean: it can do arithmetic :)

As demonstrated in 99 bottles of beer.

pmg
+1  A: 

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.

Stephen Canon
http://stackoverflow.com/questions/652788/what-is-the-worst-real-world-macros-pre-processor-abuse-youve-ever-come-across/1242177#1242177 - chaos-pp. Preprocessor abuse with style.
Andrew Y
A: 

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 thread.

highBandWidth