0
#define prod(a) (a*a)
using namespace std;
int main()
{
  int i = 3, j, k, l;
  j = prod(i++);
  cout << i << endl;
  k = prod(++i);
  cout << i << endl;
  l = prod(i+1);

  cout << i << " " << j << " " << k << " " << l;
}

Why is variable "i" incremented twice?

i.e to 5 from 3 after j=prod(i++);

Mike Kinghan
  • 55,740
  • 12
  • 153
  • 182
Vipul Sinha
  • 29
  • 1
  • 1
  • 10
  • 2
    I recommend you take some time to read [Why should I not #include ?](https://stackoverflow.com/questions/31816095/why-should-i-not-include-bits-stdc-h) – Some programmer dude Oct 24 '17 at 16:40
  • And the take-home advice: Stop using macros! With C++14 you can write something like the following and get the result you want: template auto prod(const A& a, const B& b) { return a*b; } – Gem Taylor Oct 24 '17 at 18:08

2 Answers2

2

Remember that macros are expanded in the source code, not actually called or evaluated.

That means a "call" like

prod(i++)

results in the expanded code

i++*i++

being seen by the compiler.

Many compilers allow you to stop after preprocessing, or otherwise generate preprocessed source, that you can examine to see macro expansions.


If you continue using such a macro with other expressions as arguments, you will soon see another reason they are bad.

Lets say you use

prod(2+4)

Then that will result in the expansion

2+4*2+4

which is equal to

2+(4*2)+4

which is equal to 14, not 36 which might have been expected.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
  • They don't need to go further: `i++ * i++` is already undefined behavior. Two assignments to `i` without a sequence point in between. – Bill Lynch Oct 24 '17 at 16:45
  • @BillLynch It's not really *assignment* to `i`, and with the new sequenced-before and -after rules of C++11 and later, I'm not so sure about the UB any more. If I read [this evaluation order reference](http://en.cppreference.com/w/cpp/language/eval_order) (especially [rules](http://en.cppreference.com/w/cpp/language/eval_order#Rules) 1, 2, and 4) correctly I don't think it's UB. – Some programmer dude Oct 24 '17 at 16:52
  • 1
    @Someprogrammerdude It's undefined because there is no sequenced-before relationship between the two operands of the `*` operator, and each one of them modifies `i`. – interjay Oct 24 '17 at 16:58
1

Why is variable "i" incremented twice? i.e to 5 from 3 after j=prod(i++)

Because prod() is a macro, not a function, so

k=prod(++i);

become

k=(++i * ++i);
max66
  • 65,235
  • 10
  • 71
  • 111