www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - implicit ubyte casting

reply "Saaa" <empty needmail.com> writes:
I think is very bug-prone, isn't it obvious iub should be -5?

ubyte ub = 5;
int iub = -ub; // iub now is 251

What is the reasoning to do it this way? 
Oct 01 2009
next sibling parent reply Jeremie Pelletier <jeremiep gmail.com> writes:
Saaa wrote:
 I think is very bug-prone, isn't it obvious iub should be -5?
 
 ubyte ub = 5;
 int iub = -ub; // iub now is 251
 
 What is the reasoning to do it this way? 
Minus toggles the most significant bit, be it on a signed or unsigned type. When converting it to an int, the byte being signed or unsigned does make a difference: when unsigned the number is copied as is, when signed the most significant bit (bit 7) is shifted to the most significant bit of the int (bit 31). Its therefore pretty standard logic, no warning is given since the entire ubyte range fits within an int Jeremie
Oct 01 2009
next sibling parent reply "Saaa" <empty needmail.com> writes:
Jeremie Pelletier wrote
 Saaa wrote:
 I think is very bug-prone, isn't it obvious iub should be -5?

 ubyte ub = 5;
 int iub = -ub; // iub now is 251

 What is the reasoning to do it this way?
Minus toggles the most significant bit, be it on a signed or unsigned type. When converting it to an int, the byte being signed or unsigned does make a difference: when unsigned the number is copied as is, when signed the most significant bit (bit 7) is shifted to the most significant bit of the int (bit 31). Its therefore pretty standard logic, no warning is given since the entire ubyte range fits within an int Jeremie
Thanks, but it is not that I do not know how it occurs more that I should have asked whether people use this kind of logic. For me it resulted in annoying bug like this: for(int i = nloop;i<10;i++);//ubyte nloop is created quite a few lines above.
Oct 01 2009
next sibling parent reply Jeremie Pelletier <jeremiep gmail.com> writes:
Saaa wrote:
 Jeremie Pelletier wrote
 Saaa wrote:
 I think is very bug-prone, isn't it obvious iub should be -5?

 ubyte ub = 5;
 int iub = -ub; // iub now is 251

 What is the reasoning to do it this way?
Minus toggles the most significant bit, be it on a signed or unsigned type. When converting it to an int, the byte being signed or unsigned does make a difference: when unsigned the number is copied as is, when signed the most significant bit (bit 7) is shifted to the most significant bit of the int (bit 31). Its therefore pretty standard logic, no warning is given since the entire ubyte range fits within an int Jeremie
Thanks, but it is not that I do not know how it occurs more that I should have asked whether people use this kind of logic. For me it resulted in annoying bug like this: for(int i = nloop;i<10;i++);//ubyte nloop is created quite a few lines above.
Then why use an ubyte instead of a byte or an int? You could also just do: for(int i = cast(byte)nloop; i < 10; i++) Jeremie
Oct 01 2009
parent "Saaa" <empty needmail.com> writes:
Jeremie Pelletier wrote
 Then why use an ubyte instead of a byte or an int?
I wasn't me who wrote that part of the code :)
 You could also just do:
 for(int i = cast(byte)nloop; i < 10; i++)
I forgot the minus sign: for(int i = -cast(int)nloop;i< 10; i++) Still think it is unnecessary bug-prone.
Oct 01 2009
prev sibling parent reply Don <nospam nospam.com> writes:
Saaa wrote:
 Jeremie Pelletier wrote
 Saaa wrote:
 I think is very bug-prone, isn't it obvious iub should be -5?

 ubyte ub = 5;
 int iub = -ub; // iub now is 251

 What is the reasoning to do it this way?
Minus toggles the most significant bit, be it on a signed or unsigned type. When converting it to an int, the byte being signed or unsigned does make a difference: when unsigned the number is copied as is, when signed the most significant bit (bit 7) is shifted to the most significant bit of the int (bit 31). Its therefore pretty standard logic, no warning is given since the entire ubyte range fits within an int Jeremie
Thanks, but it is not that I do not know how it occurs more that I should have asked whether people use this kind of logic. For me it resulted in annoying bug like this: for(int i = nloop;i<10;i++);//ubyte nloop is created quite a few lines above.
This has been discussed before, and it really should be an error. It's reasonable to implicitly cast between integral types of different size, and also signed<->unsigned, but performing both within the same expression is almost always a bug. It should not be possible without an explicit cast.
Oct 02 2009
parent reply Jeremie Pelletier <jeremiep gmail.com> writes:
Don wrote:
 Saaa wrote:
 Jeremie Pelletier wrote
 Saaa wrote:
 I think is very bug-prone, isn't it obvious iub should be -5?

 ubyte ub = 5;
 int iub = -ub; // iub now is 251

 What is the reasoning to do it this way?
Minus toggles the most significant bit, be it on a signed or unsigned type. When converting it to an int, the byte being signed or unsigned does make a difference: when unsigned the number is copied as is, when signed the most significant bit (bit 7) is shifted to the most significant bit of the int (bit 31). Its therefore pretty standard logic, no warning is given since the entire ubyte range fits within an int Jeremie
Thanks, but it is not that I do not know how it occurs more that I should have asked whether people use this kind of logic. For me it resulted in annoying bug like this: for(int i = nloop;i<10;i++);//ubyte nloop is created quite a few lines above.
This has been discussed before, and it really should be an error. It's reasonable to implicitly cast between integral types of different size, and also signed<->unsigned, but performing both within the same expression is almost always a bug. It should not be possible without an explicit cast.
I know VC++ shouts a warning everytime signed and unsigned integrals are mixed, maybe that's the road D should take too.
Oct 02 2009
parent Don <nospam nospam.com> writes:
Jeremie Pelletier wrote:
 Don wrote:
 Saaa wrote:
 Jeremie Pelletier wrote
 Saaa wrote:
 I think is very bug-prone, isn't it obvious iub should be -5?

 ubyte ub = 5;
 int iub = -ub; // iub now is 251

 What is the reasoning to do it this way?
Minus toggles the most significant bit, be it on a signed or unsigned type. When converting it to an int, the byte being signed or unsigned does make a difference: when unsigned the number is copied as is, when signed the most significant bit (bit 7) is shifted to the most significant bit of the int (bit 31). Its therefore pretty standard logic, no warning is given since the entire ubyte range fits within an int Jeremie
Thanks, but it is not that I do not know how it occurs more that I should have asked whether people use this kind of logic. For me it resulted in annoying bug like this: for(int i = nloop;i<10;i++);//ubyte nloop is created quite a few lines above.
This has been discussed before, and it really should be an error. It's reasonable to implicitly cast between integral types of different size, and also signed<->unsigned, but performing both within the same expression is almost always a bug. It should not be possible without an explicit cast.
I know VC++ shouts a warning everytime signed and unsigned integrals are mixed, maybe that's the road D should take too.
We can do *much* better than that. About two releases ago D2 got integer range tracking, so you can do things like: long a = someCrazyFunction(); ubyte b = (a & 7) | 0x60; // No worries! This is perfectly fine! ubyte c = a; // Error, might overflow. It just needs to be extended a bit more. It's far from finished.
Oct 02 2009
prev sibling parent reply Moritz Warning <moritzwarning web.de> writes:
On Thu, 01 Oct 2009 10:16:08 -0400, Jeremie Pelletier wrote:

 Saaa wrote:
 I think is very bug-prone, isn't it obvious iub should be -5?
 
 ubyte ub = 5;
 int iub = -ub; // iub now is 251
 
 What is the reasoning to do it this way?
Minus toggles the most significant bit, be it on a signed or unsigned type. When converting it to an int, the byte being signed or unsigned does make a difference: when unsigned the number is copied as is, when signed the most significant bit (bit 7) is shifted to the most significant bit of the int (bit 31). Its therefore pretty standard logic, no warning is given since the entire ubyte range fits within an int Jeremie
This is a troublesome behavior: ubyte z = 5; int x = -z; // x now is 251 int y = -1 * z; // y is now -5
Oct 01 2009
next sibling parent reply "Saaa" <empty needmail.com> writes:
Moritz Warning wrote
 This is a troublesome behavior:

 ubyte z = 5;
 int x = -z; // x now is 251
 int y = -1 * z; // y is now -5
Yes, troublesome is the correct word :) Does anybody ever use the =-z behaviour?
Oct 01 2009
parent reply bearophile <bearophileHUGS lycos.com> writes:
Saaa:
Does anybody ever use the =-z behaviour?<
Sometimes C programmers use something like: unsigned int x = -1; The interaction of signed-unsigned integral numbers in D is very error-prone, so much that I suggest to use unsigned integrals in D only where strictly necessary (generally when you need bitfields for bitwise operations (so not for arithmetic operations), or the less common situations where you need the full range of 1,2,4,8 bytes). Sometimes I even cast array lengths to an int and then I keep and use only such int around because in D that's safer than using a size_t (example: if you compare an unsigned int length with a negative int, your code will have a bug). I have discussed such topics several times in the main D newsgroup, and in the end no good solution has being found/accepted so far. But eventually some better solution must be found... Bye, bearophile
Oct 01 2009
parent Jarrett Billingsley <jarrett.billingsley gmail.com> writes:
On Thu, Oct 1, 2009 at 2:00 PM, bearophile <bearophileHUGS lycos.com> wrote:

 I have discussed such topics several times in the main D newsgroup, and in the
end no good solution has being found/accepted so far. But eventually some
better solution must be found...
Fucking A, bearophile. Bugzilla. How many fucking times do we have to tell you.
Oct 01 2009
prev sibling parent reply Stewart Gordon <smjg_1998 yahoo.com> writes:
Moritz Warning wrote:
<snip>
 ubyte z = 5;
 int x = -z; // x now is 251
 int y = -1 * z; // y is now -5
Indeed, I've just looked at the spec, and it appears that the promotion of all smaller integer types to int/uint applies only to binary operations. Why? It even arguably breaks the "looks like C, acts like C" principle (which I thought was the reason behind these promotions in D): ---------- #include <stdio.h> int main() { unsigned char z = 5; int x = -z; // x now is 251 int y = -1 * z; // y is now -5 printf("%d %d %d\n", z, x, y); return 0; } ---------- 5 -5 -5 ---------- (DMC 8.42n Win) Stewart.
Oct 02 2009
parent Stewart Gordon <smjg_1998 yahoo.com> writes:
Stewart Gordon wrote:
<snip>
 #include <stdio.h>
 
 int main() {
     unsigned char z = 5;
     int x = -z; // x now is 251
<snip> Needless to say, this comment is a mistake. Stewart.
Oct 02 2009
prev sibling parent reply Brad Roberts <braddr bellevue.puremagic.com> writes:
On Thu, 1 Oct 2009, Saaa wrote:

 I think is very bug-prone, isn't it obvious iub should be -5?
 
 ubyte ub = 5;
 int iub = -ub; // iub now is 251
 
 What is the reasoning to do it this way? 
The inclusion of the 'int' part obscures what I think the real problem is.. Does it make sense to use uniary-minus on a unsigned type? My answer.. no. But the counter argument that will likely come up is generic behavior. So, to prempt that.. does unary minus have any useful meaning for MOST types? My answer is still no. :) Later, Brad
Oct 01 2009
parent reply Don <nospam nospam.com> writes:
Brad Roberts wrote:
 On Thu, 1 Oct 2009, Saaa wrote:
 
 I think is very bug-prone, isn't it obvious iub should be -5?

 ubyte ub = 5;
 int iub = -ub; // iub now is 251

 What is the reasoning to do it this way? 
The inclusion of the 'int' part obscures what I think the real problem is.. Does it make sense to use uniary-minus on a unsigned type? My answer.. no.
I agree. But you don't actually need unary minus to see the problem: import std.stdio; void main() { uint a = 0; uint b = 5; long ib = a - b; writefln("%s", ib); // prints: 4294967291 }
Oct 02 2009
parent Moritz Warning <moritzwarning web.de> writes:
On Fri, 02 Oct 2009 16:25:01 +0200, Don wrote:

 Brad Roberts wrote:
 On Thu, 1 Oct 2009, Saaa wrote:
 
 I think is very bug-prone, isn't it obvious iub should be -5?

 ubyte ub = 5;
 int iub = -ub; // iub now is 251

 What is the reasoning to do it this way?
The inclusion of the 'int' part obscures what I think the real problem is.. Does it make sense to use uniary-minus on a unsigned type? My answer.. no.
I agree. But you don't actually need unary minus to see the problem: import std.stdio; void main() { uint a = 0; uint b = 5; long ib = a - b; writefln("%s", ib); // prints: 4294967291 }
I feel like walking on the edge of a cliff all time without noticing. :>
Oct 02 2009