Hi Fabian,

Fabian Raetz wrote on Mon, Feb 24, 2014 at 10:59:34PM +0100:

> while calculating my phys. memory (mb) with the 
> folllowing shellsript i get as a result -424.
> 
> sysctl -n hw.physmem returns 3849830400
> 
> ------------
> #!/bin/sh
> 
> phys_mem_bytes=`sysctl -n hw.physmem`
> phys_mem_mb=`expr $phys_mem_bytes / 1024 / 1024`
> echo $phys_mem_mb
> ----------
> 
> so i tried
> expr 2147483647 / 2 which returns 1073741824 while
> expr 2147483648 / 2 returns -1073741824
> 
> ksh(1) states that expr does Integer arithmetic.
> So is this the expected behaviour or a bug?

How strange, six replies but nobody answered your question...

The above behaviour is required by POSIX:

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap01.html#tag_17_01_02_01

  "Integer variables and constants, including the values of operands
   and option-arguments, used by the standard utilities listed in
   this volume of POSIX.1-2008 shall be implemented as equivalent
   to the ISO C standard signed long data type; floating point shall
   be implemented as equivalent to the ISO C standard double type.
   Conversions between types shall be as described in the ISO C
   standard. All variables shall be initialized to zero if they are
   not otherwise assigned by the input to the application.

   Arithmetic operators and control flow keywords shall be implemented
   as equivalent to those in the cited ISO C standard section, as
   listed in Selected ISO C Standard Operators and Control Flow
   Keywords."

So, POSIX *requires* that the output of "expr 2147483648 + 0"
and "sh -c 'echo $((2147483648 + 0))'" be machine dependent.
For example, on i386, where "long" is 32 bit, it must be negative,
but on amd64, where long is 64 bit, it must be positive.
I guess it was a bad idea to have the standard require such
weirdness; then again, this isn't exactly the only place
where POSIX requires, well, weird behaviour.

Our /bin/ksh uses "long" to store integers,
see /usr/src/bin/ksh/table.h and /usr/src/bin/ksh/expr.c,
so that seems fine.

Our /bin/expr uses "int" to store integer numbers.
As long as we have sizeof(int) == sizeof(long) on all
architectures (hum...  /me isn't a hardware hacker)
that's fine as well.

It might be a bad idea to "change this after we're done with release";
on first sight, i see nothing here that might need fixing.

Well, maybe a CAVEATS entry in some manuals might make sense,
since it doesn't appear as if many people are aware of what
POSIX requires...

Yours,
  Ingo

Reply via email to