digitalmars.D - Casting up to ints...
- Unknown W. Brackets (42/42) Apr 29 2006 One thing I've never liked, or completely understood, was the way
- Don Clugston (9/67) May 02 2006 There are very strong practical reasons. Basically it's because D
- Unknown W. Brackets (9/41) May 02 2006 No, I realize that. I definitely did not mean making everything 64 bit.
One thing I've never liked, or completely understood, was the way arithmetic casts up to ints - but no higher. Don't get me wrong, I don't at all mind it going from a short to an int... but why can't it go farther? If I add two ubytes into a ulong, I get the correct result. If I add two uints into a ulong, I get an incorrect result. I realize this is because the + operator yields an int/uint result unless one of the values is a long/ulong. But, since this doesn't happen for bytes and shorts, it seems terribly inconsistent. And when you usually deal in small numbers, you get used to numeric overflows not happening without having to cast. Then you deal with some large numbers, and create a bug. This is why I think consistency in programming is so important. So, all I'm asking is... why? I mean, what is the reason for this behavior? Is it just because, that's how C did it? Or is there a greater reason I'm missing? Otherwise it just seems like a case where we have to use the blunt instrument that is casting to make the compiler do something which is completely logical to humans. Thanks, -[Unknown] PS: For those of you who need code to understand my question: import std.stdio; int main() { ulong l1, l2; ubyte b1 = ubyte.max, b2 = ubyte.max; uint i1 = uint.max, i2 = uint.max; l1 = b1 + b2; l2 = i1 + i2; // l1 will be "right", l2 will be "wrong". writefln("Without casting:"); writefln("ubyte + ubyte = %d\n\t(%d * 2)", l1, ubyte.max); writefln("uint + uint = %d\n\t(%d * 2)", l2, uint.max); l1 = cast(ulong) b1 + cast(ulong) b2; l2 = cast(ulong) i1 + cast(ulong) i2; // l1 and l2 will both be "right". writefln("With casting:"); writefln("ubyte + ubyte = %d\n\t(%d * 2)", l1, ubyte.max); writefln("uint + uint = %d\n\t(%d * 2)", l2, uint.max); return 0; }
Apr 29 2006
Unknown W. Brackets wrote:One thing I've never liked, or completely understood, was the way arithmetic casts up to ints - but no higher. Don't get me wrong, I don't at all mind it going from a short to an int... but why can't it go farther? If I add two ubytes into a ulong, I get the correct result. If I add two uints into a ulong, I get an incorrect result. I realize this is because the + operator yields an int/uint result unless one of the values is a long/ulong. But, since this doesn't happen for bytes and shorts, it seems terribly inconsistent. And when you usually deal in small numbers, you get used to numeric overflows not happening without having to cast. Then you deal with some large numbers, and create a bug. This is why I think consistency in programming is so important. So, all I'm asking is... why? I mean, what is the reason for this behavior? Is it just because, that's how C did it? Or is there a greater reason I'm missing?There are very strong practical reasons. Basically it's because D targets 32-bit CPUs, and there is no performance cost to converting everything to 'int'. But converting everything to 'long' would be a massive performance hit on a 32-bit CPU. Even the x86-64 uses 32 bit arithmetic most of the time. It's extremely rare to find situations where ints overflow. int.max is an enormous number. This is emphatically not the case for short.max and byte.max.Otherwise it just seems like a case where we have to use the blunt instrument that is casting to make the compiler do something which is completely logical to humans. Thanks, -[Unknown] PS: For those of you who need code to understand my question: import std.stdio; int main() { ulong l1, l2; ubyte b1 = ubyte.max, b2 = ubyte.max; uint i1 = uint.max, i2 = uint.max; l1 = b1 + b2; l2 = i1 + i2; // l1 will be "right", l2 will be "wrong". writefln("Without casting:"); writefln("ubyte + ubyte = %d\n\t(%d * 2)", l1, ubyte.max); writefln("uint + uint = %d\n\t(%d * 2)", l2, uint.max); l1 = cast(ulong) b1 + cast(ulong) b2; l2 = cast(ulong) i1 + cast(ulong) i2; // l1 and l2 will both be "right". writefln("With casting:"); writefln("ubyte + ubyte = %d\n\t(%d * 2)", l1, ubyte.max); writefln("uint + uint = %d\n\t(%d * 2)", l2, uint.max); return 0; }
May 02 2006
No, I realize that. I definitely did not mean making everything 64 bit. What I did mean was, it seems like this is rather detectable: ulong a = cast(uint) b + cast(uint) c; There are, of course, other areas where it is less detectable - such as function calls and template parameters - but in that case you still have a destination type to worry about. I suppose, then, the worry would just be making the implicit conversion rules to complex. -[Unknown]Unknown W. Brackets wrote:One thing I've never liked, or completely understood, was the way arithmetic casts up to ints - but no higher. Don't get me wrong, I don't at all mind it going from a short to an int... but why can't it go farther? If I add two ubytes into a ulong, I get the correct result. If I add two uints into a ulong, I get an incorrect result. I realize this is because the + operator yields an int/uint result unless one of the values is a long/ulong. But, since this doesn't happen for bytes and shorts, it seems terribly inconsistent. And when you usually deal in small numbers, you get used to numeric overflows not happening without having to cast. Then you deal with some large numbers, and create a bug. This is why I think consistency in programming is so important. So, all I'm asking is... why? I mean, what is the reason for this behavior? Is it just because, that's how C did it? Or is there a greater reason I'm missing?There are very strong practical reasons. Basically it's because D targets 32-bit CPUs, and there is no performance cost to converting everything to 'int'. But converting everything to 'long' would be a massive performance hit on a 32-bit CPU. Even the x86-64 uses 32 bit arithmetic most of the time. It's extremely rare to find situations where ints overflow. int.max is an enormous number. This is emphatically not the case for short.max and byte.max.
May 02 2006