seg.server.fault
seg.server.fault

Reputation: 20008

C, C++ preprocessor macro

Can anyone please explain how this works

#define maxMacro(a,b) ( (a) > (b) ) ? (a) : (b) 

inline int maxInline(int a, int b)
{
  return a > b ? a : b;
}

int main()
{  
  int i = 1; j = 2, k = 0;
  k = maxMacro(i,j++); // now i = 1, j = 4 and k = 3, Why ?? Where is it incremented ?
  //reset values
  i = 1; j = 2, k = 0;
  k = maxInline(i,j++); // now i = 1, j = 3, and k = 2, Why ??
  return 0;
}

So, I want to know where exactly is the value of j incremented, while checking condition or while returning or while calling ?

UPDATE : Thanks to all, now I understand this. But just out of curiosity, why would anyone do j++ while calling method, why not increment j after calling method, this way it would be less confusing. I saw this piece of code somewhere so asking it !!

Upvotes: 4

Views: 714

Answers (7)

OJ.
OJ.

Reputation: 29401

Weird. So far nobody has mentioned that the inline function option is type-safe, where the macro isn't!

Upvotes: 0

CB Bailey
CB Bailey

Reputation: 791361

k = maxMacro(i,j++);

expands to:

k = ( (i) > (j++) ) ? (i) : (j++)

Because of the sequence point of ?: the behaviour of this is well defined. When i is less than the initial value of j, j is incremented twice and k receives the once incremented value of j.

(If i were greater than the initial value of j, then j would be incremented only once when evaluating (i) > (j++), k would be assigned that value of (i) and the second increment would not be performed.)

In:

k = maxInline(i,j++);

maxInline is called with the values i and j before increment (1 and 2), j is incremented before the function call, and k is assigned the return value of maxInline (2).

Upvotes: 10

KFro
KFro

Reputation: 764

Check out the CERT C Coding standard:

PRE00-C. Prefer inline or static functions to function-like macros

This is a great resource, lots of information about various little gotchas that one should avoid to make their code clean, stable, and secure :)

Upvotes: 0

Karl T.
Karl T.

Reputation: 502

Calling a macro is not the same as calling a function. The preprocessor replaces the reference to maxMacro(i,j++) with literal text that looks like this.

(i) > (j++) ? (i) : (j++)

A post increment operator uses the current value of its target, and then increments its target. So if i = 1 and j = 2, the following happens:

(i) > (j++) // 1 is compared to 2, and j is incremented to 3 ? (i) : (j++) 2 is greater than 1, so the "b" value is passed along. j++ is invoked again, so the previous value 3 is returned from the expression, but as a side effect, j is incremented to 4.

On the other hand, the inline function works just like a non inline function as far as how the parameter variables are treated.
j++ is referenced once when it is put on the stack as part of the function call. The function call operates with a b value of 2 and returns its result(2) while j is incremented to 3 as a side effect.

Note: your question indicates k=3 after the call to maxInline. I got k=2 after that call - the result I'd expect.

I hope this clarifies things . . .

K

Upvotes: 3

Pavel Minaev
Pavel Minaev

Reputation: 101555

Macro results in textual expansion. It happens before the compiler is even considering expressions and operators, and immediately after it had split the input text into individual tokens. Thus, the following line:

k = maxMacro(i,j++);

is exactly equivalent to the following line after macro expansion:

k = ( (i) > (j++) ) ? (i) : (j++);

Obviously, there are two increments here.

On the other hand, inline functions are just functions, and work exactly like non-inline ones for the purpose of the call. And in function calls, expressions in the argument list are evaluated first, and then their values are bound to respective parameter names inside the function body. Thus, the evaluation only happens once.

Upvotes: 6

KTC
KTC

Reputation: 9003

This is why macro is evil!

A macro is literal text subsitution by the proprocessor before your compiler gets to it so k = maxMacro(i,j++); becomes ( (i) > (j++) ) ? (i) : (j++);. I hope you see the problem here.

In the (inline) function call, the value of a and b is passed by value into the function where the initial value of i and j is passed in, after which j increment.

Upvotes: 5

Michael
Michael

Reputation: 55395

The issue is the preprocessor does just straight text substitution for macros.

maxMacro(i, j++)

becomes

( (i) > (j++) ) ? (i) : (j++)

As you can see, it does two increments when j is greater.

This is exactly why you should prefer inline functions over macros.

Upvotes: 21

Related Questions