Thread overview | ||||||||
---|---|---|---|---|---|---|---|---|
|
November 10, 2013 Overflow-safe use of unsigned integral types | ||||
---|---|---|---|---|
| ||||
One of the challenges when working with unsigned types is that automatic wraparound and implicit conversion can combine to unpleasant effect. Consider e.g.: void foo(ulong n) { writeln(n); } void main() { foo(-3); } ... which will output: 18446744073709551613 (or, ulong.max + 1 - 3). Is there a recommended way to handle this kind of potential wraparound where it is absolutely unacceptable? I've considered the following trick: void bar(T : ulong)(T n) { static if (isSigned!T) { enforce(n >= 0); // or assert, depending on your priorities } writeln(n); } ... but it would be nice if there was some kind of syntax sugar in place that would avoid such a verbose solution. I know that there have been requests for runtime overflow detection that is on by default (bearophile?), but it could be good to have some simple way to indicate "really, no overflow" even where by default it's not provided. (Motivation: suppose that you have some kind of function that takes a size_t and uses that to determine an allocation. If a negative number gets passed by accident, the function will thus try to allocate 2^64 - n elements, and your computer will have a very happy time...:-) |
November 10, 2013 Re: Overflow-safe use of unsigned integral types | ||||
---|---|---|---|---|
| ||||
Posted in reply to Joseph Rushton Wakeling | On Sunday, 10 November 2013 at 12:05:45 UTC, Joseph Rushton Wakeling wrote:
> One of the challenges when working with unsigned types is that automatic wraparound and implicit conversion can combine to unpleasant effect.
>
> Consider e.g.:
>
> void foo(ulong n)
> {
> writeln(n);
> }
>
> void main()
> {
> foo(-3);
> }
>
> ... which will output: 18446744073709551613 (or, ulong.max + 1 - 3).
>
> Is there a recommended way to handle this kind of potential wraparound where it is absolutely unacceptable? I've considered the following trick:
>
> void bar(T : ulong)(T n)
> {
> static if (isSigned!T)
> {
> enforce(n >= 0); // or assert, depending on your priorities
> }
> writeln(n);
> }
>
> ... but it would be nice if there was some kind of syntax sugar in place that would avoid such a verbose solution.
>
> I know that there have been requests for runtime overflow detection that is on by default (bearophile?), but it could be good to have some simple way to indicate "really, no overflow" even where by default it's not provided.
>
> (Motivation: suppose that you have some kind of function that takes a size_t and uses that to determine an allocation. If a negative number gets passed by accident, the function will thus try to allocate 2^64 - n elements, and your computer will have a very happy time...:-)
When writing software for embedded micros you can always check an overflow flag - is the no such mechanism on PC software?
-=mike=-
|
November 10, 2013 Re: Overflow-safe use of unsigned integral types | ||||
---|---|---|---|---|
| ||||
Posted in reply to mike james | On Sunday, 10 November 2013 at 12:19:18 UTC, mike james wrote: > When writing software for embedded micros you can always check an overflow flag - is the no such mechanism on PC software? > This is not overflow checking, it's the compiler considering a variable of type int implicitely convertible to equivalent unsigned types at bit level. I suppose it's a bug or may be the documentation is wrong (http://dlang.org/type.html): ubyte u1 = cast(byte)-1; // error, -1 cannot be represented in a ubyte ushort u2 = cast(short)-1; // error, -1 cannot be represented in a ushort These two lines are succesfully compiled by the last DMD on Windows. |
November 10, 2013 Re: Overflow-safe use of unsigned integral types | ||||
---|---|---|---|---|
| ||||
Posted in reply to rumbu | On Sunday, November 10, 2013 21:40:14 rumbu wrote: > On Sunday, 10 November 2013 at 12:19:18 UTC, mike james wrote: > > When writing software for embedded micros you can always check an overflow flag - is the no such mechanism on PC software? > > This is not overflow checking, it's the compiler considering a variable of type int implicitely convertible to equivalent unsigned types at bit level. > > I suppose it's a bug or may be the documentation is wrong > (http://dlang.org/type.html): > > ubyte u1 = cast(byte)-1; // error, -1 cannot be represented in > a ubyte > ushort u2 = cast(short)-1; // error, -1 cannot be represented in > a ushort > > These two lines are succesfully compiled by the last DMD on Windows. Casts are never checked on integral types, so the documentation is outright wrong in this case: https://d.puremagic.com/issues/show_bug.cgi?id=11493 The only checks that are done with casts are 1. whether the compiler can convert from the original type to the requested type (which has nothing to do with the values of anything - just the types) 2. whether a class instance is actually of the type beng cast to (and if it isn't, the cast results in null) When you cast, you're generally telling the compiler that you know what you're doing and don't care what the compiler thinks about whether one value should be converted to the other just so long as the types can do the conversion. - Jonathan M Davis |
November 11, 2013 Re: Overflow-safe use of unsigned integral types | ||||
---|---|---|---|---|
| ||||
Posted in reply to Joseph Rushton Wakeling | On 10.11.2013. 12:10, Joseph Rushton Wakeling wrote: > One of the challenges when working with unsigned types is that automatic wraparound and implicit conversion can combine to unpleasant effect. > > Consider e.g.: > > void foo(ulong n) > { > writeln(n); > } > > void main() > { > foo(-3); > } > > ... which will output: 18446744073709551613 (or, ulong.max + 1 - 3). > > Is there a recommended way to handle this kind of potential wraparound where it is absolutely unacceptable? I've considered the following trick: > > void bar(T : ulong)(T n) > { > static if (isSigned!T) > { > enforce(n >= 0); // or assert, depending on your priorities > } > writeln(n); > } > > ... but it would be nice if there was some kind of syntax sugar in place that would avoid such a verbose solution. > > I know that there have been requests for runtime overflow detection that is on by default (bearophile?), but it could be good to have some simple way to indicate "really, no overflow" even where by default it's not provided. > > (Motivation: suppose that you have some kind of function that takes a size_t and uses that to determine an allocation. If a negative number gets passed by accident, the function will thus try to allocate 2^64 - n elements, and your computer will have a very happy time...:-) Just for reference: http://forum.dlang.org/thread/kn3f9v$25pd$1@digitalmars.com |
November 11, 2013 Re: Overflow-safe use of unsigned integral types | ||||
---|---|---|---|---|
| ||||
Posted in reply to luka8088 | On Monday, 11 November 2013 at 07:52:34 UTC, luka8088 wrote:
> Just for reference:
> http://forum.dlang.org/thread/kn3f9v$25pd$1@digitalmars.com
Again, this has nothing to do with runtime overflow checking. It's a compiler thing. It will be nice if the compiler will not accept implicit conversions from signed types to unsigned ones for negative values. An explicit cast can be used if someone wants to represent a negative number as unsigned.
Another consequence of this behaviour is the impossibility to select automatically an overload for signed and unsigned arguments:
void foo(ulong x) {}
void foo(long x) {}
foo(-3) //=> error, both match
|
Copyright © 1999-2021 by the D Language Foundation