Why do shift operators undergo integral promotion?

Don nospam at nospam.com
Wed Aug 10 05:41:33 PDT 2011


Walter Bright wrote:
> On 8/9/2011 2:46 AM, Don wrote:
>>  From a discussion on D.learn.
>>
>> If x and y are different integral types, then in an expression like
>> x >> y
>> the integral promotion rules are applied to x and y.
>> This behaviour is obviously inherited from C, but why did C use such a
>> counter-intuitive and bug-prone rule?
>> Why isn't typeof(x >> y) simply typeof(x) ?
>> What would break if it did?
>>
>> You might think the the rule is that typeof( x >> y) is typeof( x + y),
>> but it isn't: the arithmetic conversions are NOT applied:
>> typeof(int >> long) is int, not long, BUT
>> typeof(short >> int) is int.
>> And we have this death trap (bug 2809):
>>
>> void main()
>> {
>> short s = -1;
>> ushort u = s;
>> assert( u == s );
>> assert ( (s >>> 1) == (u >>> 1) ); // FAILS
>> }
> 
> 
> That last is why we can't just change the behavior from C.

???? C doesn't even have the >>> operator.
There is no valid "backwards compatibility with C" argument here.

I cannot see ANY justification whatsoever for the behaviour of >>>.
Applying integral promotion to >>> is completely wrong. It is a bug in 
100% of cases.
Possibilities are:
(1) use typeof( x >>> y) is typeof(x)
(2) as (1), but break with C, and apply the same rule for typeof(x>>y)
(The C rule isn't too unreasonable for x << y).
(3) generate a compile error for x >>> y when x is short or byte.

Actually, I found that I misread the spec. It actually says:

"The operands must be integral types, and undergo the usual integral 
promotions. The result type is the type of the left operand after the 
promotions. The result value is the result of shifting the bits by the 
right operand's value."

So with x >>> y, the type of y actually has no effect; if x is smaller 
than int, the result is int; otherwise, the type is x.

So in fact, if x is short or byte, then x >>> y is NEVER an unsigned 
shift, regardless of what y is: it's always the same as x >> y.
But the spec says >>> performs an unsigned shift.

This disagrees with the >>>= operator as well: >>>= always performs an 
unsigned shift, even though the spec says that
x >>>= y is the same as  x = x >>> y.



Given that >>> is the same as >> for any unsigned type




More information about the Digitalmars-d mailing list