hakunami
hakunami

Reputation: 2441

How to expand this macro properly?

When I define this macro:

#define SQR(x) x*x

Let's say this expression:

SQR(a+b)

This expression will be replaced by the macro and looks like:

a+b*a+b

But, if I put a ++ operator before the expression:

++SQR(a+b)

What the expression looks like now? Is this ++ placed befor every part of SQR paramete? Like this:

++a+b*++a+b

Here I give a simple program:

#define SQR(x) x*x
int a, k = 3;
a = SQR(k+1) // 7
a = ++SQR(k+1) //9

Upvotes: 0

Views: 253

Answers (5)

Hameed
Hameed

Reputation: 2277

In your preprocessor it evaluates to ++a+b*a+b. The right way is put brackets around each term and around the whole thing, like:

#define SQR(x)  ((x)*(x))

Upvotes: 0

Joe Liu
Joe Liu

Reputation: 61

In your example, ++SQR(a+b) should be expanded as ++a+b*a+b.
So, if a == 3 and b == 1 you will get the answer 9 if the compiler evaluates it from left to right.

But your statement ++SQR(3+1) is not correct because it will be expanded as ++3+1*3+1 where ++3 is invalid.

Upvotes: 0

Michael Anderson
Michael Anderson

Reputation: 73480

For C++ the right way to define this macro is to not use a macro, but instead use:

template<typename T> static T SQR( T a ) { return a*a; }

This will get right some horrible cases that the macro gets wrong:

For example:

SQR(++a); 

with the function form ++a will be evaluated once. In the macro form you get undefined behaviour as you modify and read a value multiple times between sequence points (at least for C++)

Upvotes: 1

nneonneo
nneonneo

Reputation: 179412

When defining macros, you basically always want to put the macro parameters in parens to prevent the kind of weird behaviour in your first example, and put the result in parens so it can be safely used without side-effects. Using

#define SQR(x) ((x)*(x))

makes SQR(a+b) expand to ((a+b)*(a+b)) which would be mathematically correct (unlike a+b*a+b, which is equal to ab+a+b).

Putting things before or after a macro won't enter the macro. So ++SQR(x) becomes ++x*x in your example.

Note the following:

int a=3, b=1;
SQR(a+b) // ==> a+b*a+b = 3+1*3+1 = 7
++SQR(a+b) // ==> ++a+b*a+b ==> 4 + 1*4 + 1 = 9
           // since preincrement will affect the value of a before it is read.

You're seeing the ++SQR(a+b) appear to increment by 2 since the preincrement kicks in before a i read either time, i.e. a increments, then is used twice and so the result is 2 higher than expected.

NOTE As @JonathanLeffler points out, the latter call invokes undefined behaviour; the evaluation is not guaranteed to happen left-to-right. It might produce different results on different compilers/OSes, and thus should never be relied on.

Upvotes: 5

Rndm
Rndm

Reputation: 6860

A macro definition just replaces the code,hence it is generally preferable to put into parenthesis otherwise the code may replaced in a way you don't want.

Hence if you define it as :

#define SQR(x) ((x)*(x))

then

++SQR(a+b) = ++((a+b)*(a+b))

Upvotes: 0

Related Questions