Thread overview | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
August 07, 2011 (int << ulong) == int ? | ||||
---|---|---|---|---|
| ||||
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?
--
Dmitry Olshansky
|
August 07, 2011 Re: (int << ulong) == int ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dmitry Olshansky | 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.
- Jonathan M Davis
|
August 07, 2011 Re: (int << ulong) == int ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | > > 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. > That's right... Somehow it didn't occur to me till the last moment that bit shift is asymmetric in nature so it really shouldn't do any promotions. Sorry for the noise. -- Dmitry Olshansky |
August 07, 2011 Re: (int << ulong) == int ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dmitry Olshansky | On Monday 08 August 2011 01:42:37 Dmitry Olshansky wrote:
> > 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.
>
> That's right... Somehow it didn't occur to me till the last moment that bit shift is asymmetric in nature so it really shouldn't do any promotions. Sorry for the noise.
Yeah, well. Similar stuff happens to us all upon occasion. The real problem is when it happens frequently
- Jonathan M Davis
|
August 07, 2011 Re: (int << ulong) == int ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Dmitry Olshansky | Dmitry Olshansky: > Sorry for the noise. It's not noise, and you don't need to be sorry, in my opinion it's a D/DMD design fault. Clang gives an error on code like that: http://blog.llvm.org/2011/05/c-at-google-here-be-dragons.html See the error: example2.cc:12:25: error: shift result (10737418240) requires 35 bits to represent, but 'int' only has 32 bits [-Werror,-Wshift-overflow] long kMaxDiskSpace = 10 << 30; In my opinion D has to give a similar error. Bye, bearophile |
August 07, 2011 Re: (int << ulong) == int ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | On 08.08.2011 2:07, bearophile wrote: > Dmitry Olshansky: > >> Sorry for the noise. > It's not noise, and you don't need to be sorry, in my opinion it's a D/DMD design fault. Clang gives an error on code like that: > http://blog.llvm.org/2011/05/c-at-google-here-be-dragons.html > > See the error: > example2.cc:12:25: error: shift result (10737418240) requires 35 bits to represent, but 'int' only has 32 bits [-Werror,-Wshift-overflow] > long kMaxDiskSpace = 10<< 30; > > In my opinion D has to give a similar error. > It's useful but not a panacea. I presented a simple trimmed down example with consts, I don't think compiler can reliably identify the problem in my actual code. -- Dmitry Olshansky |
August 07, 2011 Re: (int << ulong) == int ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to bearophile | Which has nothing to do with the question about integral promotion.
On Aug 7, 2011, at 3:07 PM, bearophile <bearophileHUGS@lycos.com> wrote:
> Dmitry Olshansky:
>
>> Sorry for the noise.
>
> It's not noise, and you don't need to be sorry, in my opinion it's a D/DMD design fault. Clang gives an error on code like that:
> http://blog.llvm.org/2011/05/c-at-google-here-be-dragons.html
>
> See the error:
> example2.cc:12:25: error: shift result (10737418240) requires 35 bits to represent, but 'int' only has 32 bits [-Werror,-Wshift-overflow]
> long kMaxDiskSpace = 10 << 30;
>
> In my opinion D has to give a similar error.
>
> Bye,
> bearophile
|
August 08, 2011 Re: (int << ulong) == int ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Brad Roberts | Brad Roberts: > Which has nothing to do with the question about integral promotion. The original code was similar to this C code: int main() { unsigned int j = 42; unsigned long long k = 1 << (unsigned long long)j; return k; } If you process it with a simple C lint you get a warning 647: 1 int main() { 2 unsigned int j = 42; 3 unsigned long long k = 1 << (unsigned long long)j; 3 Info 701: Shift left of signed quantity (int) 3 Warning 647: Suspicious truncation 4 return k; 4 Info 712: Loss of precision (return) (unsigned long long to int) 5 } I think a compiler able to detect similar cases helps the OP avoid asking the question "I though left operand should be promoted to the largest integer in shift expression, isn't it?". -------------- Dmitry Olshansky: > It's useful but not a panacea. I agree, you need something more/better to improve the situation a lot. Bye, bearophile |
August 09, 2011 Re: (int << ulong) == int ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Jonathan M Davis | 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...
|
August 09, 2011 Re: (int << ulong) == int ? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Don | 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++?
- Jonathan M Davis
|
Copyright © 1999-2021 by the D Language Foundation