Topic: Unary minus applied to the smallest value of some type


Author: Maciej Sobczak <no.spam@no.spam.com>
Date: Wed, 9 Feb 2005 12:41:46 CST
Raw View
Hello,

Consider:

long n = std::numeric_limits<long>::min();
unsigned long un = -n;

Is the value of un well-defined?
If yes, what is it (standard-wise)?

On my system (32-bit Intel + gcc 3.4.2, where long is 32-bit, 2's
complement), n is -2147483648 and for un I get the "expected" value,
which is 2147483648. The problem is that this value cannot be expressed
as long, because it is greater than std::numeric_limits<long>::max().

What is the mechanism of the expression above?

--
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Michael Pryhodko" <mpryhodko@westpac.com.au>
Date: Wed, 9 Feb 2005 19:56:57 CST
Raw View
> long n = std::numeric_limits<long>::min();
> unsigned long un = -n;
[skip]
> What is the mechanism of the expression above?

C++ standard ISO/IEC 14882
3.9.1.p3,p4
4.7.p2,p3


Bye.
Sincerely yours, Michael.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: alfps@start.no (Alf P. Steinbach)
Date: Thu, 10 Feb 2005 17:16:24 GMT
Raw View
* Maciej Sobczak:
>
> long n = std::numeric_limits<long>::min();
> unsigned long un = -n;
>
> Is the value of un well-defined?

No.


> If yes, what is it (standard-wise)?

Standard-wise it's Undefined Behavior, but the de-facto standard
is to use two's complement form with no trapping, where it's well-
defined.


> On my system (32-bit Intel + gcc 3.4.2, where long is 32-bit, 2's
> complement), n is -2147483648 and for un I get the "expected" value,
> which is 2147483648. The problem is that this value cannot be expressed
> as long, because it is greater than std::numeric_limits<long>::max().
>
> What is the mechanism of the expression above?

Two's complement form (not mandated by the standard).  n = -2^31, for
your platform.  So with two's complement, arithmetic modulo 2^32,
-n = 0-n = 2^32 - n = 2^32 + 2^31 = 2^31, which when reinterpreted as unsigned
(the very simple conversion that's used for two's complement form) yields the
same, 2^31, as it must.  In general, as long as the final result is within
the number range of the result type, you get the, uh, "expected" result.  Of
course when you know what's going on you always get the expected result.

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: Maciej Sobczak <no.spam@no.spam.com>
Date: Thu, 10 Feb 2005 11:16:37 CST
Raw View
Hi,

Michael Pryhodko wrote:

>>long n = std::numeric_limits<long>::min();
>>unsigned long un = -n;
>
> [skip]
>
>>What is the mechanism of the expression above?
>
>
> C++ standard ISO/IEC 14882
> 3.9.1.p3,p4
> 4.7.p2,p3

I understand that if n is long, then -n is also long (5.3.1/7 + 4.5).

Consider:

long n = std::numeric_limits<long>::min();
long neg = -n;

There is nothing in the standard (well, I cannot find it) that would
give at least a hint what neg might be. 5.3.1/7 does not explain what
should happen in the case when -n has no representation in the
destination type.
On my platform, neg == n. Ooops.
But this is consistent with the algorithm: -x = ~x + 1

On the other hand, this:

long n = std::numeric_limits<long>::min();
long neg = -n;          // still neg == n
unsigned long un = neg; // OK, "expected" result

"works" fine, because with 2's complement nothing happens when
converting from long to unsigned long (4.7/2) and -2147483648 (as long)
and 2147483648 (as unsigned long) happen to have the same bit
representatons.

It appears to me that my original code is *not* well-defined anyway,
because of the -n part.
Is this implementation-defined? Unspecified? Undefined?

--
Maciej Sobczak : http://www.msobczak.com/
Programming    : http://www.msobczak.com/prog/

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: nospam@nospam.ucar.edu ("Thomas Mang")
Date: Thu, 10 Feb 2005 18:32:42 GMT
Raw View
"Maciej Sobczak" <no.spam@no.spam.com> schrieb im Newsbeitrag
news:420b1c4b$1_1@news.bluewin.ch...
>
> I understand that if n is long, then -n is also long (5.3.1/7 + 4.5).


Yes, the result is of type long.


>
> Consider:
>
> long n = std::numeric_limits<long>::min();
> long neg = -n;
>
> There is nothing in the standard (well, I cannot find it) that would
> give at least a hint what neg might be. 5.3.1/7 does not explain what
> should happen in the case when -n has no representation in the
> destination type.


See 5/5 -> potentially undefined behavior.


> It appears to me that my original code is *not* well-defined anyway,
> because of the -n part.
> Is this implementation-defined? Unspecified? Undefined?


According to the C99 standard, the minimum and maximum representable values
of long are implementation-defined. If the mathematical result
of -std::numeric_limits<long>::min() is not greater than LONG_MAX,
everything is fine. If not, it's undefined behavior.


Thomas


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: kanze@gabi-soft.fr
Date: Thu, 10 Feb 2005 13:17:13 CST
Raw View
Alf P. Steinbach wrote:
> * Maciej Sobczak:

> > long n = std::numeric_limits<long>::min();
> > unsigned long un = -n;

> > Is the value of un well-defined?

> No.

> > If yes, what is it (standard-wise)?

> Standard-wise it's Undefined Behavior, but the de-facto
> standard is to use two's complement form with no trapping,
> where it's well- defined.

Strictly speaking, it's unspecified whether it is undefined or
not.  On a one's complement machine, for example, it is well
defined (according to the standard).

But this is generally the case when numeric overflow is
involved.

Note that the situation is even more awkward.  You can't write a
constant expression specifying the minimum value without falling
into undefined or implementation defined behavior.  On a machine
with 32 bit longs, an expression like -2147483648 is undefined
behavior as well.  There aren't any negative integral literals,
and I can't find any exception to the undefined behavior for
constant expressions.

I hate to say it (as you can imagine:-)), but this sounds like a
very telling argument against trapping representations.  And for
just one measly little value.

I've got an idea! Let's impose 1's complement, with no negative
zeros, all one bits a trapping representation, and require
otherwise uninitialized variables to be initialized with all one
bits.  It would surely be nice to know that you trap on
uninitialized values, and we avoid the above problem.  (And
obviously, I'm joking.  I do think it would be nice to have such
a machine, but even I'm not ready to take the performance hit
such an implementation would create on a typical modern
machine.)

--
James Kanze                                           GABI Software
Conseils en informatique orient   e objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place S   mard, 78210 St.-Cyr-l'   cole, France, +33 (0)1 30 23 00 34


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Michael Pryhodko" <mpryhodko@westpac.com.au>
Date: Thu, 10 Feb 2005 23:24:56 CST
Raw View
> On a machine with 32 bit longs, an expression like -2147483648 is
> undefined behavior as well.

No. According to 5.p5 this program is 'ill-formed'.

Bye.
Sincerely yours, Michael.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Michael Pryhodko" <mpryhodko@westpac.com.au>
Date: Sat, 12 Feb 2005 13:13:55 CST
Raw View
> I understand that if n is long, then -n is also long (5.3.1/7 + 4.5).
>
> Consider:
>
> long n = std::numeric_limits<long>::min();
> long neg = -n;
>
> There is nothing in the standard (well, I cannot find it) that would
> give at least a hint what neg might be. 5.3.1/7 does not explain
> what should happen in the case when -n has no representation in the
> destination type.

Platform dependent. Or to be more precise "undefined" according to
5.p5.


> On my platform, neg == n. Ooops.
> But this is consistent with the algorithm: -x = ~x + 1

Yes, this is the result of signed integer binary representation on
IA-32 platform.


Well... as far as I remember there are four types of practical signed
integer representations in binary form. While C++ enforces
representation of unsigned integer it does not "touch" signed integers
(to be portable across hardware platforms).
Two of these representations has "-0 != 0" (in binary code). Due to
symmetrical nature of binary numbers this in results in:
INT_MIN == -INT_MAX

Another two representations has "-0 == 0" (in binary code). Due to the
same reason there should be one number witch has no negative
counterpart. On IA-32 platform this is INT_MIN, i.e.:
-INT_MIN == INT_MIN


As the result of 5.p5 you should handle such hardware platform
"features" yourself.

As the consecuence there is no "easy" way to transfer signed value over
network -- you need to invent "network" representation of signed
integer types and perform conversion whenever you need to read/write
such value from/in socket.

Bye.
Sincerely yours, Michael.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: nospam@nospam.ucar.edu ("Thomas Mang")
Date: Sat, 12 Feb 2005 19:14:10 GMT
Raw View
"Michael Pryhodko" <mpryhodko@westpac.com.au> schrieb im Newsbeitrag
news:1108084687.132494.3890@c13g2000cwb.googlegroups.com...
> > On a machine with 32 bit longs, an expression like -2147483648 is
> > undefined behavior as well.
>
> No. According to 5.p5 this program is 'ill-formed'.


You don't get so far.

According to 2.13.1/2 it's undefined behavior if 2147483648 cannot be
represented as long int.


Thomas


---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: "Michael Pryhodko" <mpryhodko@westpac.com.au>
Date: Sun, 13 Feb 2005 13:04:54 CST
Raw View
>> No. According to 5.p5 this program is 'ill-formed'.
>
> You don't get so far.
>
> According to 2.13.1/2 it's undefined behavior if 2147483648 cannot
> be represented as long int.

:)) Also according 2.13.1/3 program is ill-formed. So it seems that
'-2147483648' causes both undefined behaviour and ill-formed program.

I beg my pardon, James, my 'No' was technically wrong :)

Bye.
Sincerely yours, Michael.

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]





Author: alfps@start.no (Alf P. Steinbach)
Date: Mon, 14 Feb 2005 01:02:53 GMT
Raw View
* kanze@gabi-soft.fr:
>
> I've got an idea! Let's impose 1's complement

If the moderators allow, :-)

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.jamesd.demon.co.uk/csc/faq.html                       ]