Subject: Re: Documentation of abs(3), div(3) etc.
To: Martijn van Buul <pino+gmane_os_netbsd_devel_general@dohd.org>
From: Krister Walfridsson <cato@df.lth.se>
List: tech-misc
Date: 02/11/2007 04:52:11
On Sat, 10 Feb 2007, Martijn van Buul wrote:

> Not sure if this is a real improvement, and it *certainly* doesn't
> make things work all of a sudden. There is one thing the implementation-
> defined behaviour cannot do: Suddenly make -INT_MIN fito a signed int.

Please re-read the whole of my previous mail closely.  The point is to 
disprove your statement:

> My point was that the proposed change indicates is pointless, doesn't
> change a single opcode, and obviously indicates a lack of understanding.

by showing that abs(INT_MIN) is undefined in our current implementation, 
but that it becomes defined (i.e. as abs(INT_MIN) == INT_MIN) by the 
proposed change.

(But I want to point out that it would be silly change the implementation 
to make abs(INT_MIN) defined.  It is much better to just say that the 
value is undefined as Christian Biere proposed.)



> In all likelyness, the result will be the same: After
>
> signed int foo = abs(INT_MIN);
>
> foo will probably end up containing an unchanged INT_MIN - which is
> what the manpage is hinting at :)

Kind of.  If you directly do a "printf("%d\n", foo);", it will
probably print the value of INT_MIN.  But let us look at a slightly
more interesting example.

Consider the following code containing the two implementations of abs:

   #include <stdio.h>

   static int abs1(int a)
   {
     return a < 0 ? -a : a;
   }

   static int abs2(int a)
   {
     return a < 0 ? -(unsigned)a  : a;
   }

   void bar(int a)
   {
     int foo;

     foo = abs1(a);
     if (foo < 0)
       printf("abs1(%d) < 0\n", a);

     foo = abs2(a);
     if (foo < 0)
       printf("abs2(%d) < 0\n", a);
   }

and we call the function foo() from an other file:

   #include <limits.h>

   int main(void)
   {
     bar(INT_MIN);
     return 0;
   }

Compiling this with a current gcc such as

   gcc version 4.3.0 20070106 (experimental)

gives the result

   > ./a.out
   abs2(-2147483648) < 0

i.e. gcc manages to eliminate the first if-statement because it knows that 
"if (abs1(a) < 0)" always is false (or undefined.  But it do not need to 
care about undefined values as no valid C program may invoke undefined 
behavior).  But the result of foo2(a) is defined for all possible values 
of a, and thus gives the expected result.

    /Krister