简体   繁体   中英

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 ?

  • a. using macro
  • b. using inline method

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 !!

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.

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

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.

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

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 ab 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

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM