Thread overview | |||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
June 11, 2013 Why there is too many uneccessary casts? | ||||
---|---|---|---|---|
| ||||
ubyte k = 10; ubyte c = k + 1; This code fails to compile because of: Error: cannot implicitly convert expression (cast(int)k + 1) of type int to ubyte Why? It's pain in the ass, i think. My code contains only casts then. |
June 11, 2013 Re: Why there is too many uneccessary casts? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Temtaime | On Tue, 11 Jun 2013 12:12:25 +0200, Temtaime <temtaime@gmail.com> wrote: > ubyte k = 10; > ubyte c = k + 1; > > This code fails to compile because of: Error: cannot implicitly convert expression (cast(int)k + 1) of type int to ubyte > > Why? It's pain in the ass, i think. My code contains only casts then. Because it's unsafe. The compiler does not know if k+1 fits in a ubyte. (True, in this case it could know it, but it does not, and in the general case it can't know) -- Simen |
June 11, 2013 Re: Why there is too many uneccessary casts? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjaeraas | There is overflow and it can be with int too. It's standard behavior. |
June 11, 2013 Re: Why there is too many uneccessary casts? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Temtaime | On Tue, 11 Jun 2013 12:39:47 +0200, Temtaime <temtaime@gmail.com> wrote: > There is overflow and it can be with int too. > It's standard behavior. Indeed. And a class is a void* is an int is a char is a double? That's perfectly possible - it's all just memory anyway. D has chosen to do it like this to prevent common errors. If you think the cast stands out like a sore thumb, use: ubyte k = 10; ubyte c = (k + 1) & 0xFF; That way, value range propagation ensures the result fits in a ubyte, and the code compiles happily. -- Simen |
June 11, 2013 Re: Why there is too many uneccessary casts? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Temtaime | Temtaime: > ubyte k = 10; > ubyte c = k + 1; > > This code fails to compile because of: Error: cannot implicitly convert expression (cast(int)k + 1) of type int to ubyte > > Why? It's pain in the ass, i think. My code contains only casts then. I agree that sometimes that's a pain. Currently D performs a range analysis only inside one expression, and not across different ones. One way to avoid the cast is to perform a masking: void main() { immutable ubyte UB = ubyte.max; ubyte k = 10; ubyte c = (k + 1) & UB; } The solution is to improve D. Beside fixing this bug: http://d.puremagic.com/issues/show_bug.cgi?id=9107 A first step is to keep the range value for immutable variables, but this is not enough to solve your problem because your k is mutable: http://d.puremagic.com/issues/show_bug.cgi?id=10018 Your case is very simple. It's just a sequence of instructions, with no gotos, no jumps, no control instructions, no function calls. Introducing some simple conservative rules for such simple situation is possible. But the advantage of the current situation is that it make usually easy to know where to put a cast and where it's not needed. The more complex the rules become, the harder is to know where the casts are not needed. Bye, bearophile |
June 11, 2013 Re: Why there is too many uneccessary casts? | ||||
---|---|---|---|---|
| ||||
On Tue, 11 Jun 2013 13:15:11 +0200, Simen Kjaeraas <simen.kjaras@gmail.com> wrote: > On Tue, 11 Jun 2013 12:39:47 +0200, Temtaime <temtaime@gmail.com> wrote: > >> There is overflow and it can be with int too. >> It's standard behavior. > > Indeed. And a class is a void* is an int is a char is a double? That's > perfectly possible - it's all just memory anyway. D has chosen to do > it like this to prevent common errors. If you think the cast stands > out like a sore thumb, use: > > ubyte k = 10; > ubyte c = (k + 1) & 0xFF; > > That way, value range propagation ensures the result fits in a ubyte, > and the code compiles happily. Also worth noting: both & 0xFF and cast(ubyte) shows that the programmer has considered the possibility of overflow (or just programmed blindly, but let's assume a rational programmer), something your original code did not. Looking at this code: ubyte a = foo(); ubyte b = a + 1; doSomethingWith(b); It's not possible for me to know if that code works correctly if foo() returns 255 - perhaps it should actually be saturated (255+1 == 255), perhaps it should even throw an exception. With this code: ubyte a = foo(); ubyte b = cast(ubyte)(a + 1); // or (a + 1) & 0xFF; doSomethingWith(b); The programmer has documented something: If this causes an overflow, the value in b is still correct. Explicit is better than implicit. -- Simen |
June 11, 2013 Re: Why there is too many uneccessary casts? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Simen Kjaeraas | No. I means, that uint a = uint.max; uint b = a + 1; writeln(b); Works OK. Why? Compiler doesn't know if a + b fits in uint, right? Then why overflow with ints are accepted? So your example is meaningless. |
June 11, 2013 Re: Why there is too many uneccessary casts? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Temtaime | On Tue, 11 Jun 2013 13:46:11 +0200, Temtaime <temtaime@gmail.com> wrote: > No. I means, that > > uint a = uint.max; > uint b = a + 1; > writeln(b); > > Works OK. > Why? Compiler doesn't know if a + b fits in uint, right? > Then why overflow with ints are accepted? Because there's a limit to how far this goes without introducing arbitrary-precision numbers. There is indeed an argument for uint+uint giving a ulong answer, and I'm confused myself at why this is not the case. > So your example is meaningless. No. -- Simen |
June 11, 2013 Re: Why there is too many uneccessary casts? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Temtaime | Temtaime: > Why? Compiler doesn't know if a + b fits in uint, right? > Then why overflow with ints are accepted? It's an inconstancy based on practical considerations. Walter decided that applying the same rule to uint/int/long causes too many casts in normal problems. And the range of a 32 bit int is much larger than the range of a ubyte/byte/ushort/short, so in normal programs the probability of overflowing an int by mistake is much lower than overflowing a ubyte. > So your example is meaningless. You should be more gentle if you want people to keep giving you answers :-) Bye, bearophile |
June 11, 2013 Re: Why there is too many uneccessary casts? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Temtaime | On Tuesday, 11 June 2013 at 10:12:27 UTC, Temtaime wrote:
> ubyte k = 10;
> ubyte c = k + 1;
>
> This code fails to compile because of: Error: cannot implicitly convert expression (cast(int)k + 1) of type int to ubyte
The reason is arithmetic operations transform the operands into ints, that's why the error says cast(int)k. Then it thinks int is too big for ubyte. It really isn't about overflow, it is about truncation.
That's why uint + 1 is fine. The result there is still 32 bits so assigning it to a 32 bit number is no problem, even if it does overflow. But k + 1 is promoted to int first, so it is a 32 bit number and now the compiler complains that you are trying to shove it into an 8 bit variable. Unless it can prove the result still fits in 8 bits, it complains, and it doesn't look outside the immediate line of code to try to prove it. So it thinks k can be 255, and 255 + 1 = 256, which doesn't fit in 8 bits.
The promotion to int is something D inherited from C and probably isn't going anywhere.
|
Copyright © 1999-2021 by the D Language Foundation