Can the C preprocessor perform integer arithmetic? - c-preprocessor

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?

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

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

YES, I mean: it can do arithmetic :)
As demonstrated in 99 bottles of beer.

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.

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.

Be carefull when doing arithmetic: add parenthesis.
#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 parenthesis:
#define TOTALSIZE (SIZE4 + SIZE8)

Related

CMacro and integer arithmetic

I need to implement something like this but using CMacro:
int a = //some constant;
int x = //constant
int c = //constant
int y = a*x+b;
I've tried something like:
#define A 3
#define X 6
#define B 8
#define Y ((A)*(X) + (B))
However if I use the flag -E in the gcc it shows me 3*6 + 8.
Isn't there any way to perform integer arithmetic using CMacro, before the substitution I mean?
My purpose would be something like, just a piece of code...:
#define func_impl(NY,NX,R) \
void func_#NY_#NX(int* y, int* x) { \ //x size NX, y size NY
int tmp[2*NX - R]; \
for(int i = 0; i < 2*NX - R; i++) tmp[i] = 0; \
//other processing operations... \
}
I know both NX, NY and R a priori, although they're generated by another program. So basically I want to avoid to let the program P1 to generate too many macro constants if possible.
However if I use the flag -E in the gcc it shows me 3*6 + 8.
That's actually fine, because any decent compiler will perfom constant folding on such expression, so you'll end up with 26 within machine code.
Other than that, you might try using an static inline function, which has advantage of being type-safe. Macros are pretty error-prone and are rather difficult to debug.
No, macros only serve as textual replacement, nothing else.
The only place where the preprocessor evaluates expressions is in its own #if/#else construct. But there it might actually be a bit different than you think at a first look, because the types for integers are always [u]intmax_t.

Casting with #if in C

Why this code gives an error:
#include <stdio.h>
#define Rep (int)6
int main(){
#if Rep==6
printf("T");
#else
printf("F");
#endif
return 0;
}
Why does it refuse the casting?
Is it a 'preprocessor error' or a 'compiler error'?
This is a preprocessor error. It happens because the preprocessor does not understand how to cast a variable. You cannot use any C code with #if, just simple numbers, or macros which expand to a number.
If you cannot modify Rep, you can work around this with a helper macro, which removes the casting from the beginning:
#include <stdio.h>
#define X(x)
#define Y(x) X x
#define Rep (int)6
int main(void) {
#if Y(Rep) == 6
printf("%d\n", Y(Rep)); // prints 6
#endif
return 0;
}
Preprossor macros that combine casts and that still should work in #if are easy to write: you just add a little + before the number. In your case
#define Rep ((int)+6)
The preprocessor replaces identifiers that it doesn't know by 0 so the end result is the same value.
But also, the cast in your Rep macro by itself is quite useless. 6 is an int, anyhow. So better avoid a cast for all integer types that have their own literals, combinations of U and L as suffix should do in most cases.

C programming: testing oversized shift

Negative and oversized bit shifts are undefined behaviour. But I need to do positive/negative shifts in many places of my code, so I wrote a generic function for that:
uint64_t shift_bit(uint64_t b, int i)
{
// detect oversized shift
assert(-63 <= i && i <= 63);
return i >= 0 ? b << i : b >> -i;
}
That takes care of negative shifts. But what about oversized shift?
Is a C compiler allowed to optimize away the assert()? (Or to replace it with assert(true), which has the same effect).
Is there a way to code around it?
PS: Please base your answers only on what the standard guarantees, not on what your specific compiler does. My program needs to be 100% portable, as it gets compiled for many different platforms, and with many different compilers.
assert() is replaced to "nothing" on release.
#ifdef NDEBUG
#define assert(exp) ((void)0)
#else
#define assert(exp) /*implementation*/
#endif

Output of a C program

I have written the following C program. The output is 32. Why is this?
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#define max 10+2
int main(){
int i;
i = max * max;
printf("\n%d\n",i);
return 0;
}
(I am learning C and am relatively new to it.)
#define max 10+2
This is the preprocessor. it is not smart.
it is stupid.
it just replaces text.
max*max
will resolve to
10+2*10+2
which is
10+(2*10)+2
because of operator precedence, which is
10 + 20 + 2
i.e. 32
Furthermore, you should avoid preprocessor macros whenever you can and use static const instead. You may or may not want to also consider using a const variable or an enum instead of a #define; each have their tradeoffs, refer to the similar question: "static const" vs "#define" vs "enum".
If you want to stick to preprocessor, then you could just use:
#define max (10+2)
Since parenthesised code will take operator precendence.
Since max is a macro, it gets expanded textually, so your code comes out with:
i = 10 +2 * 10 + 2;
For a macro like this, you generally want to add parentheses:
#define max (10+2)
So your expression will expand to:
i = (10+2) * (10+2);
The compiler sees this
i = 10 + 2*10 +2 = 32
You should do the macro definition like this
#define max (10+2)
Operator precedence is a funny thing. PEMDAS = Parenthises, Exponents, Multiply, Divide, Add, Subtract.
This is going to resolve to equal to 10 + (2 * 10) + 2.
First is 10*2 which equals 20.
Now it reads 10 + 20 + 2.
The rest should be clear.
You should exercise control over your arithmetics whenever desired.

Conditional Compilation and compile time evaluation of expressions in ANSI C

I would like to do the following, but the compiler doesn't like it:
unsigned short foo = 1;
// do something with foo
#if sizeof(short) * CHAR_BIT > 16
foo &= 0xffff;
#endif
I know this expression can always be fully evaluated at compile time, but maybe it's only evaluated after the preprocessor does it's thing? Is this possible in ANSI C or do I just have to do the check at run time?
You can't use sizeof in a preprocessor expression. You might want to do something like this instead:
#include <limits.h>
#if SHRT_MAX > 32767
/* do soemthing */
#endif
If your aim is to stop compilation when a data type is the wrong size, the following technique is useful:
struct _check_type_sizes
{
int int_is_4_bytes[(sizeof(int) == 4) ? 1 : -1];
int short_is_2_bytes[(sizeof(short) == 2) ? 1 : -1];
};
(The sizeof() function is interpreted here by the compiler, not the preprocessor.)
The main disadvantage of this method is that the compiler error isn't very obvious. Make sure you write a very clear comment.

Resources