(int << ulong) == int ?

Jonathan M Davis jmdavisProg at gmx.com
Tue Aug 9 02:11:56 PDT 2011


On Tuesday 09 August 2011 11:03:11 Don wrote:
> Jonathan M Davis wrote:
> > On Tuesday 09 August 2011 09:32:41 Don wrote:
> >> Jonathan M Davis wrote:
> >>> On Monday 08 August 2011 00:33:31 Dmitry Olshansky wrote:
> >>>> Just lost the best part of an hour figuring the cause of this
> >>>> small
> >>>> problem, consider:
> >>>> 
> >>>> void main()
> >>>> {
> >>>> 
> >>>>          uint j = 42;
> >>>>          ulong k = 1<<cast(ulong)j;
> >>>>          ulong m = 1UL<<j;
> >>>>          assert(k == 1024);//both asserts do pass
> >>>>          assert(m == (1UL<<42));
> >>>> 
> >>>> }
> >>>> 
> >>>> I though left operand should be promoted to the largest integer in
> >>>> shift
> >>>> expression, isn't it?
> >>> 
> >>> I would not expect that type of integer being used to give the
> >>> number of bits to shift to affect thet type of integer being
> >>> shifted. It doesn't generally make much sense to shift more than
> >>> the size of the integer type being shifted, and that can always fit
> >>> in a byte. So, why would the type of the integer being used to give
> >>> the number of bits to shift matter? It's like an index. The index
> >>> doesn't affect the type of what's being indexed. It just gives you
> >>> an index.
> >>> 
> >>> You have to deal with integer promotions and all that when doing
> >>> arithmetic, because arithmetic needs to be done with a like number
> >>> of
> >>> bits on both sides of the operation. But with shifting, all your
> >>> doing
> >>> is asking it to shift some number of bits. The type which holds the
> >>> number of bits shouldn't really matter. I wouldn't expect _any_
> >>> integer
> >>> promotions to occur in a shift expression. If you want to affect
> >>> what's
> >>> being shifted, then cast what's being shifted.
> >> 
> >> Your intuition is wrong!
> >> 
> >> expression.html explicitly states the operands to shifts undergo
> >> integral promotions. But they don't get arithmetic conversions.
> >> 
> >> I think this is terrible.
> >> 
> >> short x = -1;
> >> x >>>= 1;
> >> 
> >> Guess what x is...
> > 
> > That's just downright weird. Why would any integral promotions occur
> > with a shift? And given your example, the current behavior seems like a
> > bad design. Is this some weird hold-over from C/C++?
> 
> I think it must be, some silly idea of 'simplifying' things by applying
> the same promotion rules to all binary operators. Given that 256-bit
> integers still don't seem to be coming any time soon, even shifts by a
> signed byte shouldn't require promotion.
> Incidentally, the x86 instruction set doesn't use integers, you can only
> shift a 64-bit number by an 8-bit value. So x << y always compiles to
> x << cast(ubyte)y. Shift should not need a common type.
> 
> This is one of those things that can cause problems, but never helps.

Given that fact, wouldn't it be safe to change the behavior so that it 
_doesn't_ do promotions? It sounds like the only case where it would change 
behavior (either for code ported from C/C++ or for existing D code) is if it's 
doing something wrong.

- Jonathan M Davis


More information about the Digitalmars-d-learn mailing list