0
#include<iostream>
#include<conio.h>
#define test(X) X*X

using namespace std;

int main()
{
    int i=3,j;
    j= test(++i);
    cout<<j;
    getch();
}

I was expecting output of 20 ( 4*5) but I am getting value of 25. can anyone point out where I misunderstood.

Thanks.

Deanie
  • 2,316
  • 2
  • 19
  • 35
Ravi Kasaudhan
  • 69
  • 1
  • 2
  • 8
  • 4
    Undefined Behaviour. Nothing to do with macros. Will find the link. – BoBTFish Dec 20 '13 at 21:13
  • 4
    _"nothing" to with macros_? You couldn't get any "normal" function `test` to evaluate it's parameter expression twice – sehe Dec 20 '13 at 21:17
  • @sehe: Yet you could have a function which took two arguments and write `test(++i, ++i);`, or just `test(++i + ++i);`. It has nothing to do with macros, macros are simply one avenue of causing the problem. – Ed S. Dec 20 '13 at 21:22
  • 1
    "simply one avenue" - Macros are just ---famous--- infamous for causing this without the caller noticing. Yes, you can write the same lack of sequence points by other means, but it's not "Nothing to do with macros" here. – sehe Dec 20 '13 at 21:31
  • Doesn't it seem like people ask questions they already know the answer to? – Fiddling Bits Dec 20 '13 at 21:56
  • btw, many people write their macros in cap, eg `TEST(x)`, and one reason they do that is to warn/remind them it isn't a function and may not be safe to use arguments that have side effects. I suspect you should follow this rule too. – RichardPlunkett Dec 21 '13 at 05:55

2 Answers2

0

The statement

j= test(++i); 

will invoke undefined behavior. On expanding macro test(X) it looks like

j = ++i * ++i; //i is modifying twice.   

Here i is modifying twice between two sequence points.

C-FAQ-3.8:.

Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression. Furthermore, the prior value shall be accessed only to determine the value to be stored.

C11: 3.4.3; undefined behavior:

behavior, upon use of a nonportable or erroneous program construct or of erroneous data, for which this International Standard imposes no requirements

NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable results, to behaving during translation or program execution in a documented manner characteristic of the environment (with or without the issuance of a diagnostic message), to terminating a translation or execution (with the issuance of a diagnostic message).

Community
  • 1
  • 1
haccks
  • 104,019
  • 25
  • 176
  • 264
-2

Macros effectively copy/paste. So, it turns into:

++i * ++i

Don't think of it like a function. And, this is undefined behavior because it modifies i twice between sequence points.

Also, macros are evil. Don't use them. (And for the obnoxious downvoter: Very very rarely macros are a necessary evil. However, they are still evil)

David
  • 27,652
  • 18
  • 89
  • 138
  • 4
    -1 for saying that macros are evil. They have their place. – Jacobm001 Dec 20 '13 at 21:15
  • 1
    @MooingDuck `int test(int x){ return x*x; } test(++i);` In what way would a function have the same problem? – David Dec 20 '13 at 21:16
  • They do, for #include – ScarletAmaranth Dec 20 '13 at 21:16
  • @Jacobm001 Updated. Enjoy your macros buddy. – David Dec 20 '13 at 21:17
  • @Dave: That's really still not a fair answer. Although they can slightly inflate code, they are good for small repetitive tasks since they require far less involvement of the EIP and can reduce the general memory footprint. – Jacobm001 Dec 20 '13 at 21:19
  • 1
    @Jacobm001 An optimizer can decide give you the same benefits from your function when it will be beneficial. It's smarter than you. I started to list all the ways macros are horrible, but decided you can use the internet. It's well established. – David Dec 20 '13 at 21:24
  • I am concerned about the output. I read about the undefined behaviour and got more confused... Can anyone elaborate with my example – Ravi Kasaudhan Dec 20 '13 at 21:26
  • 1
    -1 again for the "macros are evil" line. That tells me nothing except that you lack experience in areas where they are very useful. – Ed S. Dec 20 '13 at 21:27
  • +1 I agree that macros are evil, at least as often as they're not. They have their place for diagnostic dump functions, etc, but are too often used because they're "clever", even though that display of cleverness obscures the structure of the code and adds very little. – Hot Licks Dec 20 '13 at 21:31
  • Macros, used for code generation or conditional compliation, are *not* evil. That’s just FUD. Macros to replace functions or constants – yes, *those* are evil. – Konrad Rudolph Dec 20 '13 at 21:33
  • 1
    @KonradRudolph -I'd say they are a *necessary* evil for the first cases. I think this answer is causing grief because the question is tagged both `C` and `C++`. Macros are basically unavoidable in C (certainly in ANSI C), but C++ removes the need for most of the common abuses. – Roddy Dec 20 '13 at 21:42
  • @Roddy As evil as templates, or pointers, then. This dilutes the meaning of the word between all usefulness. – Konrad Rudolph Dec 20 '13 at 21:49
  • @KonradRudolph I agree (with 2 comments ago), but your clean example (conditional compilation) is usually just #defines, not function-like macros. – David Dec 20 '13 at 22:00
  • There was a macro in an early version of the SUN JVM that was something like `#define IS_SOMETHING if (someVal == anotherVal) {`. Let me assure you that that is most definitely evil. – Hot Licks Dec 21 '13 at 19:03