Path: utzoo!utgpu!news-server.csri.toronto.edu!cs.utexas.edu!samsung!umich!sharkey!amara!mcdaniel From: mcdaniel@amara.uucp (Tim McDaniel) Newsgroups: comp.lang.c Subject: Re: Computing the absolute value of an integer Message-ID: Date: 7 May 90 19:41:04 GMT References: <11679@june.cs.washington.edu> <1990May4.121950.22726@agate.berkeley.edu> Sender: news@adi.COM Organization: Applied Dynamics Int'l. Lines: 71 In-reply-to: c60c-3cf@e260-3c.berkeley.edu's message of 4 May 90 12:19:50 GMT c60c-3cf@e260-3c.berkeley.edu (Dan Kogai) writes: >What's wrong with using a macro like the following >#define abs(x) (((x) >= 0) ? (x) : -(x)) {et cetera} One problem is the use of a macro. Why optimize if "abs" is not in the critical path for your program? In many dubuggers, you can't work with a macro. If the argument x has a side effect, as in j = abs(i++); it would be evaluated twice. You can't take the address of a macro. "What's [really] wrong" is in the original article by ka@cs.washington.edu (Kenneth Almquist): > I want a function that will compute the absolute value of any > integer that can be stored in a variable of type int. What makes > this difficult is that on some machines the absolute value of the ^^ ^^^^ ^^^^^^^^ ^^^ ^^^^^^^^ ^^^^^ ^^ ^^^ > most negative integer will not fit in an int. ^^^^ ^^^^^^^^ ^^^^^^^ ^^^^ ^^^ ^^^ ^^ ^^ ^^^ E.g. suppose we have a two's-complement machine where ints are 2 bytes long. Then ints range from -32768 to 32767 inclusive. However, note that 32768 is NOT in the valid range, so int x = -32768; -x; may overflow. ANSI C does not guarantee what happens when a signed integer value overflows. A conforming implementation may validly send 220 volts AC at 100 amps thru your terminal upon overflow. Kenneth continues (edited): > The following solution works on all machines I know of: > unsigned int my_abs(int a) { > if (a >= 0) > return a; > else > return -a; > } > Does anyone know of machines on which this will fail? In practice, no. To explain: this code depends on -INT_MIN == INT_MIN, which is true on most machines. (Two's-complement negation is "flip the bits and add one"; with a 2-byte int, INT_MIN is 8000 hex. Flip (invert) the bits to get 7fff and add one, getting 8000 again, if integer overflow is ignored, and it usually is.) ANSI C says that INT_MIN assigned to an unsigned int on a two's-complement machine will produce -INT_MIN. > Can anyone suggest a more portable implementation? How about unsigned int my_abs(int a) { if (a >= 0) return (unsigned)a; else return -(unsigned)a; } ? Casting signed to unsigned is well-defined under ANSI C, and ought to work the same under pre-ANSI. Ditto for "-" on an unsigned value. The first cast is not strictly necessary, but I use two rules: - NEVER mix signed and unsigned values, unless using explicit casts. (And then make sure you know what'll happen.) - ALWAYS REMEMBER: sizeof may be unsigned! (The second one is harder to remember.) Failing to follow these rules can lead to extremely subtle bugs. -- Tim McDaniel Applied Dynamics International, Ann Arbor, MI Internet: mcdaniel@adi.com ((else mcdaniel%amara.uucp@mailgw.cc.umich.edu)) UUCP: {uunet,sharkey}!amara!mcdaniel