TITLE: Modifying an object twice in the same expression PROBLEM: DAVID PAGE (Biggles) I was discussing with a friend the dangers of using macros and the advantages of inline functions etc. We made a little example of a macro for calculating the square of a number. Here it is. #define SQUARE(x) (x*x) int xx=SQUARE(++x); [...] The output we expected was of course [...] BUT Borland C++ 3.1 gives us [...] Perplexing ! [...] RESPONSE: jamshid (Jamshid Afshar) jamshid@ses.com The fact that you didn't get your "expected" output ain't a deficiency in BC++ or any other compiler. The use of the macro above causes undefined results in C and C++ because it modifies a variable twice in the same expression. A compiler might output what you expect, it might output what BC++ outputs, or it might output "macros suck, he-he-he-he". See the comp.lang.c Frequently Asked Questions list (/rtfm.mit.edu: /pub/usenet/comp.lang.c/*) section 4.1 and 4.2 for a more complete explanation. I have included the sections below -- please read it and the rest of the comp.lang.c FAQ. Not only does much of it apply to C++ as well, but I've found that many C++ programmers who think they know C well really don't. Note, an inline SQUARE() function IS much better than a macro because it makes the code: int xx=SQUARE(++x); well defined. C++ books should probably be more specific about WHY the inline function is better than the macro and C/C++ compilers should try harder to diagnose this common error. ---from Steve Summit's (C) comp.lang.c FAQ------- 4.1: Why doesn't this code: a[i] = i++; work? A: The subexpression i++ causes a side effect -- it modifies i's value -- which leads to undefined behavior if i is also referenced elsewhere in the same expression. References: ANSI Sec. 3.3 p. 39. 4.2: Under my compiler, the code int i = 7; printf("%d\n", i++ * i++); prints 49. Regardless of the order of evaluation, shouldn't it print 56? A: Although the postincrement and postdecrement operators ++ and -- perform the operations after yielding the former value, the implication of "after" is often misunderstood. It is _not_ guaranteed that the operation is performed immediately after giving up the previous value and before any other part of the expression is evaluated. It is merely guaranteed that the update will be performed sometime before the expression is considered "finished" (before the next "sequence point," in ANSI C's terminology). In the example, the compiler chose to multiply the previous value by itself and to perform both increments afterwards. The behavior of code which contains multiple, ambiguous side effects has always been undefined. Don't even try to find out how your compiler implements such things (contrary to the ill- advised exercises in many C textbooks); as K&R wisely point out, "if you don't know _how_ they are done on various machines, that innocence may help to protect you." References: K&R I Sec. 2.12 p. 50; K&R II Sec. 2.12 p. 54; ANSI Sec. 3.3 p. 39; CT&P Sec. 3.7 p. 47; PCS Sec. 9.5 pp. 120-1. (Ignore H&S Sec. 7.12 pp. 190-1, which is obsolete.)