6

Possible Duplicate:
Could anyone explain these undefined behaviors (i = i++ + ++i , i = i++, etc…)

#include<stdio.h>
#include<conio.h>

#define SQ(x) x*x

void main()
{
   int a1 , a2;
   int b1 , b2;

   a1 = 2;
   a2 = 2;

   b1 = 0;
   b2 = 0;

   b1 = SQ(a1++);
   b2 = SQ(++a2);

   printf("Frist = %d",b1);
   printf("Second = %d",b2);
}

I know what is the output of the code.

as #define work in other programe that way it is not working in above code Why.?

Community
  • 1
  • 1
Nirav
  • 61
  • 1
  • 2
  • 1
    What happens when you compile and execute this? Errors? Weird results? What? – FrustratedWithFormsDesigner Nov 02 '10 at 15:51
  • 2
    What is the output you expect, and what are you getting? I'm pretty sure that in x++ * x++ and ++y*++y* it's undefined whether the first increment has happened by the time the second one is evaluated, so the value you get will vary from environment to environment – The Archetypal Paul Nov 02 '10 at 15:52
  • In your original question, there was a typo (`#deifne` instead of `#define`) I corrected now, make sure the code you use is correct. – schnaader Nov 02 '10 at 15:52

9 Answers9

16

The result of an expression with more than one ++ operator on the same variable is officially an undefined behavior in C.

Seva Alekseyev
  • 59,826
  • 25
  • 160
  • 281
  • Is this technically "undefined behavior"? I thought it was "unspecified behavior", which is still bad, but limits the implementation to certain choices (which in this case do not include crashing). – aschepler Nov 02 '10 at 16:02
  • Yes, it's definitely undefined ;). – eq- Nov 02 '10 at 16:04
  • By the way, this answer is not exactly correct. An expression may modify the same variable multiple times - the behavior is undefined only if between these modifications there is no sequence point (i.e. &&, ||, ?:, comma operator or function call) – eq- Nov 02 '10 at 16:09
  • A language lawyer I'm not :) Nor do I play one on TV. – Seva Alekseyev Nov 02 '10 at 16:27
7

#define is an instruction to the preprocessor to literally replace each occurrence of the macro with its expansion. So the relevant lines in your code will pass to the compiler as:

b1 = a1++ * a1++;
b2 = ++a2 * ++a2;

As Seva states, these expressions are officially undefined; but even if we take what is arguably the most sensible reading you'll still get b1 = 2 * 3; and b2 = 3 * 4; (with both a1 and a2 set to 4 after the lines.

Chowlett
  • 45,935
  • 20
  • 116
  • 150
3

Both uses of SQ invoke undefined behaviour, as they are assigning to a1 and a2 more than once per sequence point. You should not pass expressions with side effects such as assignments or increments to macros.

Puppy
  • 144,682
  • 38
  • 256
  • 465
2

because define just replaces the expression. so you get in result:

b1 = (a1++)*(a1++);
b2 = (++a2)*(++a2;

So, you get double increment twice. It results in undefined behaviour.

Vladimir Ivanov
  • 42,730
  • 18
  • 77
  • 103
2

Congratulations! You have just discovered why it is a bad idea to use macros for this sort of thing. As a general rule, only make something a macro if it cannot be done using a function. In this case, SQ could easily be implemented as a function instead:

int sq (int x)
{
    return x * x;
}
Dan Moulding
  • 211,373
  • 23
  • 97
  • 98
1

Wrap the operands in the macro between parenthesis:

#define SQ(X) (X)*(X)

Also, try not to operate with x++ and x in the same assignment. Could lead to undefined behavior.

Cheers!

salezica
  • 74,081
  • 25
  • 105
  • 166
1

The lines

b1 = SQ(a1++);
b2 = SQ(++a2);

expand to

b1 = a1++ * a1++;
b2 = ++a2 * ++a2;

which invoke undefined behavior (an object may have its value modified at most once between sequence points), meaning any result is considered "correct".

That's the problem with these sorts of macros; you really want the argument to be evaluated once, but because of the expansion it gets evaluated twice.

There's also the problem with calling it with an expression like

x = SQ(a + b);

This will expand to

x = a + b * a + b;

which is probably not what you wanted. To preserve operator precedence, the expansion should be wrapped in (), such as

#define SQ(x) (x) * (x)
John Bode
  • 119,563
  • 19
  • 122
  • 198
  • Re your last point, you also need to wrap the whole expression in parentheses i.e. `#define SQ(x) ((x) * (x))` otherwise expressions like `x = -SQ(4)` might give unexpected results. – JeremyP Nov 02 '10 at 16:21
  • @JeremyP: oops, yes, you're right. Can you tell I don't use macros like this a lot? – John Bode Nov 02 '10 at 16:32
0

Look at the code as it will be expanded by the preprocessor:

b1 = a1++ * a1++;
b2 = ++a2 * ++a2;

This is undefined behavior, because you are modifying a variable more than once without a sequence point between them.

Darron
  • 21,309
  • 5
  • 49
  • 53
0

I really don't know what your question is, but maybe you have problems with your expected output... Be aware that #define is a "simple" text-replacement that is running before your code compiles. This text-replacement has no respect for scope or syntactic correctnes.. it just replaces anything that matches with what you said it. In your case it would not really make a square of the result of "a++", instead it would generate this code: b1 = a++ * a++;

If you look here: Question about C programming you can see some explanations as why "a++ * a++" is officially undefined behaviour.

Community
  • 1
  • 1
lx.
  • 2,317
  • 1
  • 22
  • 32