Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Posting-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!henry From: henry@utzoo.UUCP (Henry Spencer) Newsgroups: comp.lang.c Subject: Re: Expressions compared to zero in *c* Message-ID: <8581@utzoo.UUCP> Date: Tue, 15-Sep-87 12:01:07 EDT Article-I.D.: utzoo.8581 Posted: Tue Sep 15 12:01:07 1987 Date-Received: Tue, 15-Sep-87 12:01:07 EDT References: <374@mcdsun.UUCP>, <766@maccs.UUCP> Organization: U of Toronto Zoology Lines: 50 > However, if the comparison is done as a - b > 0, everything magically > works thanks to the properties of two's complement arithmetic under > overflows. In fact it works regardless of whether a,b are signed long or > unsigned long (however the result a - b _must_ be considered as a signed long > value, necessitating a cast if a,b are unsigned)... Thou hast missed a fine point: this subtraction should always be done with unsigned longs, because the result of overflow in signed subtraction is *undefined*. That is, it could give you a trap or the wrong answer. The latter possibility is real; many C compilers can AND WILL give wrong results in certain situations involving signed overflow. The two statements "the compiler ignores the possibility of overflow" and "the generated code ignores overflows" are ***NOT*** synonymous. If the compiler is ignoring the issue of overflows, it ignores the possibility that overflow may put the hardware into an unexpected state. For unsigned arithmetic, it is (theoretically... sigh) required to cope properly. Those who think I am kidding might try compiling and running the following. (If your machine is 16 bits, change "2000000000" to "32000" everywhere.) ---------- main() { int foo; foo = 2000000000; if ((foo += 2000000000) < 0) printf("%d is negative\n", foo); else printf("%d is non-negative (!)\n", foo); } ---------- Now, for extra marks, change the declaration of foo to unsigned and the condition to "((int)(foo += 2000000000) < 0)" and see whether the people who wrote your compiler were aware of the issue! (It may console them to know that Dennis Ritchie overlooked this one too... although he had the excuse that he wrote his compiler before X3J11 made it explicit that unsigned arithmetic never overflows.) For those whose machines give the right answer, and who can't understand what the fuss is about, on many pdp11-derived machines (VAX, 68k, etc etc) the compiler will cleverly realize that for a comparison against 0, it only needs to test the condition codes set by the addition. Unfortunately, the condition codes from the addition are the same as those of a comparison of the result to 0 *only if* the addition did not overflow. Change the "0" to "1" and the problem goes away. -- "There's a lot more to do in space | Henry Spencer @ U of Toronto Zoology than sending people to Mars." --Bova | {allegra,ihnp4,decvax,utai}!utzoo!henry