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

3
  • 1
    What happens when you compile and execute this? Errors? Weird results? What? Commented Nov 2, 2010 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 Commented Nov 2, 2010 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. Commented Nov 2, 2010 at 15:52

9 Answers 9

16

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

Sign up to request clarification or add additional context in comments.

4 Comments

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).
Yes, it's definitely undefined ;).
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)
A language lawyer I'm not :) Nor do I play one on TV.
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.

Comments

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.

Comments

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.

2 Comments

You added some parentheses to the expansion. That doesn't make any difference in this case, but sometimes it makes a huge difference.
@Darron Agree with you. For sake of readability here.
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;
}

1 Comment

+1 for a more important point than C++ language arcana
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!

Comments

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)

2 Comments

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: oops, yes, you're right. Can you tell I don't use macros like this a lot?
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.

Comments

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.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.