Topic: use of usigned in the standard
Author: shepherd@debussy.sbi.com (Marc Shepherd)
Date: 1995/06/15 Raw View
In article 14b@minnie.cs.ucsb.edu, schapel@minnie.cs.ucsb.edu (Steve E. Chapel) writes:
[examples of signed-to-unsigned conversion elided]
>Should the draft standard be modified to dissallow signed-to-unsigned
>conversion in cases such as this, where bizarre results can occur?
>In my opinion, yes, if a way can be found to do this without introducing
>further complications.
>
IMO, there is no way to change this behavior without introducing further
complications, and therefore, there is approximately zero probability that
such a change will be made.
C++ inherited all of its integral conversion rules from C. No one disputes
that the rules are imperfect and can, at times, be the source of annoying bugs
and surprising results.
However, it would be a source of big-time confusion if C and C++ had different
rules about something so fundamental as integral conversions. Furthermore,
any change would silently change the meaning of thousands of programs and
do serious injury to the Committee's credibility.
Luckily, a decent compiler can warn about arithmetic expressions that mix
signed and unsigned quantities. In my view, such expressions are nearly
always candidates for rewriting or qualification with an explicit cast.
---
Marc Shepherd
Salomon Brothers Inc
shepherd@schubert.sbi.com The opinions I express are no one's but mine!
Author: rossberg@ips.cs.tu-bs.de (Andreas Rossberg)
Date: 1995/06/15 Raw View
James Kanze US/ESC 60/3/141 #40763 (kanze@lts.sel.alcatel.de) wrote:
: In article <3r738d$muu@hpsystem1.informatik.tu-muenchen.de>
: schuenem@informatik.tu-muenchen.de (Ulf Schuenemann) writes:
: |>
: |> Does anyone know why the conversions semantics was decided this way?
:
: Probably so that things like:
:
: unsigned u ;
: if ( u > 5 ) // ...
:
: would work as expected. (One doesn't expect the 5 to cause u to
: convert to signed.)
Maybe the literal 5 should have been defined as being unsigned, then. (One
could expect that.)
- Andreas Rossberg
Author: osinski@valis.cs.nyu.edu (Ed Osinski)
Date: 1995/06/16 Raw View
In article <DA7qrM.MD1@ips.cs.tu-bs.de>, rossberg@ips.cs.tu-bs.de (Andreas Rossberg) writes:
|> James Kanze US/ESC 60/3/141 #40763 (kanze@lts.sel.alcatel.de) wrote:
|> : In article <3r738d$muu@hpsystem1.informatik.tu-muenchen.de>
|> : schuenem@informatik.tu-muenchen.de (Ulf Schuenemann) writes:
|> : |>
|> : |> Does anyone know why the conversions semantics was decided this way?
|> :
|> : Probably so that things like:
|> :
|> : unsigned u ;
|> : if ( u > 5 ) // ...
|> :
|> : would work as expected. (One doesn't expect the 5 to cause u to
|> : convert to signed.)
|>
|> Maybe the literal 5 should have been defined as being unsigned, then. (One
|> could expect that.)
...or overloaded to be either signed or unsigned, depending on the
context. But that would probably create more problems than it solves.
C compatibility would probably be one of the victims.
--
---------------------------------------------------------------------
Ed Osinski
Computer Science Department, New York University
E-mail: osinski@cs.nyu.edu
---------------------------------------------------------------------
"No, no, no, don't tug on that. You never know what it might be attached to."
-- Buckaroo Bonzai to assistant during brain surgery
Author: kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763)
Date: 1995/06/13 Raw View
In article <3r738d$muu@hpsystem1.informatik.tu-muenchen.de>
schuenem@informatik.tu-muenchen.de (Ulf Schuenemann) writes:
|> In article <3qnbtc$t24@galaxy.ucr.edu>, thp@cs.ucr.edu (Tom Payne) writes:
|> [..]
|> |> Personally, I avoid unsigned as an arithmetic value because of the
|> |> (IMHO) unnatural conversions semantics for binary operators:
|> |>
|> |> Otherwise, if eigher operand is unsigned, the other is
|> |> converted to unsigned. (ARM p.34)
|> |>
|> |> which is almost always the opposite of what I want and expect. "Once
|> |> bitten, twice shy."
|> [ Without any intent to suppose such a fundamental change at this time: ]
|> Does anyone know why the conversions semantics was decided this way?
Probably so that things like:
unsigned u ;
if ( u > 5 ) // ...
would work as expected. (One doesn't expect the 5 to cause u to
convert to signed.)
--
James Kanze Tel.: (+33) 88 14 49 00 email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils en informatique industrielle --
-- Beratung in industrieller Datenverarbeitung
Author: schapel@minnie.cs.ucsb.edu (Steve E. Chapel)
Date: 1995/06/13 Raw View
jjb@watson.ibm.com (John Barton) writes:
>In article <ITZ.95Jun2023131@kronstadt.rahul.net>, itz@kronstadt.rahul.net (Ian T Zimmerman) writes:
>|> In article <3qhpg7$jkt@ra.ibr.cs.tu-bs.de> ti953017@rzcipa03.rz.tu-bs.de (Andreas Rossberg) writes:
>|> A question occured to me when I read some of the library parts of
>|> the draft. Why is it, that no serious use of unsigned has been made?
>|>
>|> For example, several members of the numeric_limits class template
>|> should better be declared unsigned. A whole set of typedefs describe
>|> naturally unsigned properties, nevertheless they are defined to be
>|> signed integral types (and sometimes -1 is abused as a special fault
>|> value - reminds me of the discussion about null iterators on c.s.c++
>|> a while ago).
>|>
>|> It appears somewhat odd, that even the language's own library doesn't
>|> use a certain one of the language's features approprietly (IMHO).
>|>
>|> I dunno. I used to have similar feelings about the C library. Then
>|> somebody explained to me that people in the U*x world _intentionally_
>|> used signed integers for all truly numeric variables and reserved
>|> `unsigned' only for bit masks and the like. I now think that makes
>|> excellent sense. From an abstract point of view there is really only
>|> one kind of integer. The set of positive integers is a _subset_ but
>|> not a _subtype_ of the integer type (no closure under subtraction
>|> etc.) Having a real primitive unsigned type just muddies the typing
>|> rules with all kind of implementation baggage. Modula-2 had an exact
>|> analog of `unsigned'; it was dropped from Modula-3.
> In other words, "unsigned int" does not mean "positive integers".
>Andreas, try this program:
>#include <iostream.h>
>int main() {
> unsigned i = 0;
> cout << i-1 << endl;
>}
>My machine gives 4294967295. If you use "unsigned"
>its difficult to check for negative numbers and bugs involving
>negative numbers look bizzarre rather than negative number bugs.
I had an even more obscure bug due to strangeness caused by the signed-to-
unsigned conversion.
Try this program on your machine:
#include <iostream.h>
#include <iomanip.h>
int main() {
unsigned long Modulus = 7;
long N = -1;
unsigned short Modulus2 = 7;
short M = -1;
cout << N % Modulus << endl;
cout << M % Modulus2 << endl;
}
The output on my machine is:
3
-1
For the first number, I expect 6 instead of 3. What happens is that -1
is converted to its unsigned counterpart of 4294967295 on my machine, then
the remainder after dividing by 7 is calculated to be 3.
The second result is even more confusing, since -1 should be converted to
65535 on my machine, and 65535 mod 7 is 1!
This bug came up because I wrote a class to do arithmetic over the integers
modulo n. I thought it was perfectly natural to use unsigned int to store
the modulus of my numbers. I implemented the class by doing normal (signed)
integer arithmetic, then normalizing the result of that calculation with %.
I realized that I had to check for negative results from %, since the behavior
of the % operator is not completely defined for negative numbers (i.e.
-11 % 7 could be -4 or 3). But -1 % 7 should be either -1 or 6; 3 is
completely bizarre! After realizing that negative numbers were not being
correctly normalized, I stored the modulus as a signed int, and my program
immediately worked fine!
Should the draft standard be modified to dissallow signed-to-unsigned
conversion in cases such as this, where bizarre results can occur?
In my opinion, yes, if a way can be found to do this without introducing
further complications.
Any thoughts on this?
--
Steve Chapel schapel@cs.ucsb.edu | http://www.cs.ucsb.edu/~schapel
University of California, Santa Barbara | finger -l schapel@eci1.ucsb.edu
Author: kanze@lts.sel.alcatel.de (James Kanze US/ESC 60/3/141 #40763)
Date: 1995/06/14 Raw View
In article <3rlvec$14b@minnie.cs.ucsb.edu> schapel@minnie.cs.ucsb.edu
(Steve E. Chapel) writes:
|> jjb@watson.ibm.com (John Barton) writes:
|> >In article <ITZ.95Jun2023131@kronstadt.rahul.net>,
|> >itz@kronstadt.rahul.net (Ian T Zimmerman) writes:
[Concerning unsigned...]
|> >|> From an abstract point of view there is really only
|> >|> one kind of integer. The set of positive integers is a _subset_ but
|> >|> not a _subtype_ of the integer type (no closure under subtraction
|> >|> etc.) Having a real primitive unsigned type just muddies the typing
|> >|> rules with all kind of implementation baggage. Modula-2 had an exact
|> >|> analog of `unsigned'; it was dropped from Modula-3.
There is a fundamental difference between Modula-n and C/C++ in this
regard. C/C++ implicitly converts between the types.
For a long time, I traditionally used `unsigned' much as I used
`cardinal' in Modula. In discussions here on the net, Fergus
Henderson made it clear (to me, at least), that this is *not* good C++
practice, because the unchecked conversions convert negative values to
large positive values, without any possibility of detecting the error.
|> > In other words, "unsigned int" does not mean "positive integers".
|> >Andreas, try this program:
|> >#include <iostream.h>
|> >int main() {
|> > unsigned i = 0;
|> > cout << i-1 << endl;
|> >}
|> >My machine gives 4294967295. If you use "unsigned"
|> >its difficult to check for negative numbers and bugs involving
|> >negative numbers look bizzarre rather than negative number bugs.
|> I had an even more obscure bug due to strangeness caused by the signed-to-
|> unsigned conversion.
|> Try this program on your machine:
|> #include <iostream.h>
|> #include <iomanip.h>
|> int main() {
|> unsigned long Modulus = 7;
|> long N = -1;
|> unsigned short Modulus2 = 7;
|> short M = -1;
|> cout << N % Modulus << endl;
|> cout << M % Modulus2 << endl;
|> }
The `%' is *not* defined for negative values! (Nor is `/', when used
on int's.) So the above program invokes undefined (or unspecified,
I'm not sure which) behavior.
|> The output on my machine is:
|> 3
|> -1
|> For the first number, I expect 6 instead of 3. What happens is that -1
|> is converted to its unsigned counterpart of 4294967295 on my machine, then
|> the remainder after dividing by 7 is calculated to be 3.
Even if no unsigned where involve, the results may vary. All that is
guaranteed is that `(a/b) * b + (a%b) == a', supposing b!=0. In
particular, whether -1/7 equals 0 or -1 is either not specified, or
implementation defined. (I forget the exact wording, but it is
sufficient to mean that you don't want to do it.)
|> The second result is even more confusing, since -1 should be converted to
|> 65535 on my machine, and 65535 mod 7 is 1!
Frankly, I suspect an error here. I don't have my C standard handy,
but I believe that the actual `%' operation should be carried out
using unsigned arithmetic. In which case, there is *no* way that the
results could be negative.
|> This bug came up because I wrote a class to do arithmetic over the integers
|> modulo n. I thought it was perfectly natural to use unsigned int to store
|> the modulus of my numbers. I implemented the class by doing normal (signed)
|> integer arithmetic, then normalizing the result of that calculation with %.
|> I realized that I had to check for negative results from %, since the behavior
|> of the % operator is not completely defined for negative numbers (i.e.
|> -11 % 7 could be -4 or 3). But -1 % 7 should be either -1 or 6; 3 is
|> completely bizarre! After realizing that negative numbers were not being
|> correctly normalized, I stored the modulus as a signed int, and my program
|> immediately worked fine!
Except, of course, that you still have to check that the input is not
negative. (In theory, of course. In practice, I think it would be
sufficient to check if the results were negative, and if so, add the
modulus. If portability is not an issue, I believe that there are
implementations on which this will even work without any checks.)
|> Should the draft standard be modified to dissallow signed-to-unsigned
|> conversion in cases such as this, where bizarre results can occur?
|> In my opinion, yes, if a way can be found to do this without introducing
|> further complications.
|> Any thoughts on this?
Short of banning dangerous conversions completely, or making them
checked, I don't think it can be done. Personally, I would like to
ban any implicit conversion which could potentially change the value,
and require the programmer to use either static_cast (unchecked) or
dynamic_cast (checked). Given the number of programs this would
break, and the issues of C compatibility, I'm not holding my breath
until it happens.
--
James Kanze Tel.: (+33) 88 14 49 00 email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs-Bourgeois, F-67000 Strasbourg, France
Conseils en informatique industrielle --
-- Beratung in industrieller Datenverarbeitung
Author: shepherd@debussy.sbi.com (Marc Shepherd)
Date: 1995/06/12 Raw View
In article 95Jun2023131@kronstadt.rahul.net, itz@kronstadt.rahul.net (Ian T Zimmerman) writes:
>In article <3qhpg7$jkt@ra.ibr.cs.tu-bs.de> ti953017@rzcipa03.rz.tu-bs.de (Andreas Rossberg) writes:
> A question occured to me when I read some of the library parts of
> the draft. Why is it, that no serious use of unsigned has been made?
>
> For example, several members of the numeric_limits class template
> should better be declared unsigned. A whole set of typedefs describe
> naturally unsigned properties, nevertheless they are defined to be
> signed integral types (and sometimes -1 is abused as a special fault
> value - reminds me of the discussion about null iterators on c.s.c++
> a while ago).
>
> It appears somewhat odd, that even the language's own library doesn't
> use a certain one of the language's features approprietly (IMHO).
>
>I dunno. I used to have similar feelings about the C library. Then
>somebody explained to me that people in the U*x world _intentionally_
>used signed integers for all truly numeric variables and reserved
>`unsigned' only for bit masks and the like.
When you use an 'unsigned' quantity in the same arithmetic expression
as a 'signed' quantity, various automatic conversions take place. Although
these conversions are copiously documented, most programmers unfortunately
do not know them by heart, and therefore may expect a different result than
they get.
As an antidote to this common problem, many style guides recommend using
plain ints/shorts/longs, even when you know (semantically) that a particular
variable can never go negative. If you use signed arithmetic exclusively,
there's one less opportunity for surprise.
(BTW, most good compilers have a warning level that complains about
arithmetic expressions containing a mixture of signed and unsigned
values. Programmers should take such warnings very seriously.)
---
Marc Shepherd
Salomon Brothers Inc
shepherd@schubert.sbi.com The opinions I express are no one's but mine!
Author: jjb@watson.ibm.com (John Barton)
Date: 1995/06/10 Raw View
In article <ITZ.95Jun2023131@kronstadt.rahul.net>, itz@kronstadt.rahul.net (Ian T Zimmerman) writes:
|> In article <3qhpg7$jkt@ra.ibr.cs.tu-bs.de> ti953017@rzcipa03.rz.tu-bs.de (Andreas Rossberg) writes:
|> A question occured to me when I read some of the library parts of
|> the draft. Why is it, that no serious use of unsigned has been made?
|>
|> For example, several members of the numeric_limits class template
|> should better be declared unsigned. A whole set of typedefs describe
|> naturally unsigned properties, nevertheless they are defined to be
|> signed integral types (and sometimes -1 is abused as a special fault
|> value - reminds me of the discussion about null iterators on c.s.c++
|> a while ago).
|>
|> It appears somewhat odd, that even the language's own library doesn't
|> use a certain one of the language's features approprietly (IMHO).
|>
|> I dunno. I used to have similar feelings about the C library. Then
|> somebody explained to me that people in the U*x world _intentionally_
|> used signed integers for all truly numeric variables and reserved
|> `unsigned' only for bit masks and the like. I now think that makes
|> excellent sense. From an abstract point of view there is really only
|> one kind of integer. The set of positive integers is a _subset_ but
|> not a _subtype_ of the integer type (no closure under subtraction
|> etc.) Having a real primitive unsigned type just muddies the typing
|> rules with all kind of implementation baggage. Modula-2 had an exact
|> analog of `unsigned'; it was dropped from Modula-3.
In other words, "unsigned int" does not mean "positive integers".
Andreas, try this program:
#include <iostream.h>
int main() {
unsigned i = 0;
cout << i-1 << endl;
}
My machine gives 4294967295. If you use "unsigned"
its difficult to check for negative numbers and bugs involving
negative numbers look bizzarre rather than negative number bugs.
--
John.
John J. Barton jjb@watson.ibm.com (914)784-6645
<http://www.research.ibm.com/xw-SoftwareTechnology>
H1-C13 IBM Watson Research Center P.O. Box 704 Hawthorne NY 10598
Author: schuenem@informatik.tu-muenchen.de (Ulf Schuenemann)
Date: 1995/06/08 Raw View
In article <3qnbtc$t24@galaxy.ucr.edu>, thp@cs.ucr.edu (Tom Payne) writes:
[..]
|> Personally, I avoid unsigned as an arithmetic value because of the
|> (IMHO) unnatural conversions semantics for binary operators:
|>
|> Otherwise, if eigher operand is unsigned, the other is
|> converted to unsigned. (ARM p.34)
|>
|> which is almost always the opposite of what I want and expect. "Once
|> bitten, twice shy."
[ Without any intent to suppose such a fundamental change at this time: ]
Does anyone know why the conversions semantics was decided this way?
If it where the other way (conversion to signed), we would get rid of the
special any-negative-becomes-huge-positive problem of the current decision
(and in return would get the less often huge-unsigned-becomes-negative problem).
Ulf Schuenemann
--------------------------------------------------------------------
Ulf Sch nemann
Fakult t f r Informatik, Technische Universit t M nchen, Germany.
email: schuenem@informatik.tu-muenchen.de
Author: itz@kronstadt.rahul.net (Ian T Zimmerman)
Date: 1995/06/02 Raw View
In article <3qhpg7$jkt@ra.ibr.cs.tu-bs.de> ti953017@rzcipa03.rz.tu-bs.de (Andreas Rossberg) writes:
A question occured to me when I read some of the library parts of
the draft. Why is it, that no serious use of unsigned has been made?
For example, several members of the numeric_limits class template
should better be declared unsigned. A whole set of typedefs describe
naturally unsigned properties, nevertheless they are defined to be
signed integral types (and sometimes -1 is abused as a special fault
value - reminds me of the discussion about null iterators on c.s.c++
a while ago).
It appears somewhat odd, that even the language's own library doesn't
use a certain one of the language's features approprietly (IMHO).
I dunno. I used to have similar feelings about the C library. Then
somebody explained to me that people in the U*x world _intentionally_
used signed integers for all truly numeric variables and reserved
`unsigned' only for bit masks and the like. I now think that makes
excellent sense. From an abstract point of view there is really only
one kind of integer. The set of positive integers is a _subset_ but
not a _subtype_ of the integer type (no closure under subtraction
etc.) Having a real primitive unsigned type just muddies the typing
rules with all kind of implementation baggage. Modula-2 had an exact
analog of `unsigned'; it was dropped from Modula-3.
--
Ian T Zimmerman +-------------------------------------------+
P.O. Box 13445 I With so many executioners available, I
Berkeley, California 94712 I suicide is a really foolish thing to do. I
USA <itz@rahul.net> +-------------------------------------------+
Author: thp@cs.ucr.edu (Tom Payne)
Date: 1995/06/02 Raw View
Ian T Zimmerman (itz@kronstadt.rahul.net) wrote:
: In article <3qhpg7$jkt@ra.ibr.cs.tu-bs.de> ti953017@rzcipa03.rz.tu-bs.de (Andreas Rossberg) writes:
: A question occured to me when I read some of the library parts of
: the draft. Why is it, that no serious use of unsigned has been made?
: I dunno. I used to have similar feelings about the C library. Then
: somebody explained to me that people in the U*x world _intentionally_
: used signed integers for all truly numeric variables and reserved
: `unsigned' only for bit masks and the like. I now think that makes
: excellent sense. From an abstract point of view there is really only
: one kind of integer. The set of positive integers is a _subset_ but
: not a _subtype_ of the integer type (no closure under subtraction
Personally, I avoid unsigned as an arithmetic value because of the
(IMHO) unnatural conversions semantics for binary operators:
Otherwise, if eigher operand is nsigned, the other is
converted to unsigned. (ARM p.34)
which is almost always the opposite of what I want and expect. "Once
bitten, twice shy."
Tom Payne
Author: ti953017@rzcipa03.rz.tu-bs.de (Andreas Rossberg)
Date: 1995/05/31 Raw View
A question occured to me when I read some of the library parts of
the draft. Why is it, that no serious use of unsigned has been made?
For example, several members of the numeric_limits class template
should better be declared unsigned. A whole set of typedefs describe
naturally unsigned properties, nevertheless they are defined to be
signed integral types (and sometimes -1 is abused as a special fault
value - reminds me of the discussion about null iterators on c.s.c++
a while ago).
It appears somewhat odd, that even the language's own library doesn't
use a certain one of the language's features approprietly (IMHO).
- Andreas Rossberg