Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!mailrus!cs.utexas.edu!uunet!ncrlnk!cipc1!gmaranca From: gmaranca@cipc1.Dayton.NCR.COM (Gabriel Maranca) Newsgroups: comp.lang.c Subject: Type-independent ABS Keywords: abs labs Message-ID: <1392@cipc1.Dayton.NCR.COM> Date: 5 Oct 89 13:37:26 GMT Reply-To: gmaranca@cipc1.Dayton.NCR.COM (Gabriel Maranca) Organization: NCR Controller's Division - F*A*S*T - Dayton, OH Lines: 86 I am posting a few answers to my question on why isn't the abs function type independent. I wish to thank everybody. Based on the answers, my ABS macro now has become: #define ABS(x) (((x) < 0) ? (-(x)) : (x)) If anybody decides to use it, the macro is faster and more generic than the standard abs and labs functions, but invocations like ABS(k++) won't work properly. A complex expression may be passed as a parameter, as long as evaluating it three times doesn't cause problems. If the expression is very complex, or if it is a function call, the ABS macro may wind up being slower than the abs and labs functions. These are the answers I got: chris@mimsy.UUCP (Chris Torek) writes: > >#define ABS(x) (((long)(x) < 0L)? -(x) : (x)) > The cast to long and the 0L are both unnecessary. If left out, this > ABS will do its comparison in whatever type x has. Thanks for illuminating me. I didn't know context type promotion was a standard feature of C (I knew my compiler did it). This will greatly simplify my code (I was doing these silly casts everywhere, thinking I was creating more portable code). > Note that ABS(k++) and the like will do `mysterious' things, and Thanks again. This explains why abs is not a macro. > that on most machines, ABS(largest_negative_integer) is either > a (compile or run)-time trap or simply largest_negative_integer. If you have time, could you explain how is this problem resolved by the standard library function? flaps@dgp.toronto.edu (Alan J Rosenthal) writes: > It is portable but will only work for ints and longs. But the following > is portable and will work for all types, including unsigned long, double, > and long long if it exists: > #define ABS(x) (((x) < 0) ? -(x) : (x)) > The zero will get promoted to the correct type. Thanks. This is the same answer I got from Chris. gwyn@brl.arpa (Doug Gwyn) writes: > That's just the way it's always been. English is not my native language, so I may have misinterpreted your statement. If you mean the abs function has always been type independent, my K&R book (second edition - pg. 253) makes reference to two functions: int abs(int n) and long labs(long n) But maybe you meant the abs function has always been type dependent, which doesn't seem a very good reason for keeping it the same way. > Note that if its argument has side effects, funny behavior may occur. Thanks. I will avoid passing such arguments. This IS a good reason for keeping the abs and labs functions the same. bill davidsen (davidsen@crdos1.crd.GE.COM) writes: > 1. instead of -(x) use (-(x)). Good point. I had overlooked this potential trap in my original macro. > 2. you might want to use (double) to work with more types Per Chris and Alan, a better approach is to remove the cast altogether. This should work with any current or future data type. Please let me know if this is not true for some C compiler. > 3. you still have to be careful about what you use for an > argument to avoid things like ABS(x[m++]) which are only > evaluated once if ABS is a procedure. OK. I wonder how many standard library "functions" are implemented as macros that could behave similarly? Or have such macros consistently been avoided because of this side effect? By the way, Bill, I am not a "she" (do not confuse Gabriel and Gabrielle) ;-) --- #Gabriel Maranca #Gabriel.Maranca@cipc1.Dayton.NCR.COM #...!uunet!ncrlnk!cipc1!gmaranca -- #Gabriel Maranca #Gabriel.Maranca@cipc1.Dayton.NCR.COM #...!uunet!ncrlnk!cipc1!gmaranca