0

I am aware that many arithmetic operators can mean e.g. adding or multiplying short can give an int answer.

But Surely bitwise ones should respect the input types?

Specifically:

Uint16 x = 123;
Uint16 ffff = 0xffff;
x = x ^ 0xffff; 
x = x ^ ffff;

Whereas as @dmitry points out, x ^= 0xffff is just fine.

Both are invalid. Is there a good reason or do I just cast the result and get on with my day?

I have a real case more like:

x = (x >> 8) ^ buffer[(x & 0xFF) ^ y];

And am trying to work out: how many casts do I actually need?!

Mr. Boy
  • 60,845
  • 93
  • 320
  • 589
  • 1
    "Because that's what the spec says" – canton7 Jan 20 '20 at 11:54
  • 1
    "Is there a good reason or do I just cast the result and get on with my day?" - that latter, basically. The reason *behind* why it works this way is that fundamentally, at the IL level, `ushort` doesn't exist on the stack - heck, the concept of "signed" only exists at the point you perform operations; so in IL terms: it loads an integer *from* a `ushort` (widening it), and then xors two integers, leaving an integer; it doesn't want to assume you want to narrow it back (because it *can't* do that without knowing what you want to do with the narrowed value) – Marc Gravell Jan 20 '20 at 11:56
  • 1
    Why do you think the higher-order bits will be set? – canton7 Jan 20 '20 at 11:56
  • 2
    `x ^= 0xffff;` and `x ^= ffff;` will compile – Dmitry Bychenko Jan 20 '20 at 11:57
  • _When both operands are of other integral types (sbyte, byte, short, ushort, or char), their values are converted to the int type, which is also the result type of an operation._ from msdn [specs](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators/bitwise-and-shift-operators) – Pavel Anikhouski Jan 20 '20 at 11:57
  • @DmitryBychenko that's very handy to know. But why? – Mr. Boy Jan 20 '20 at 12:00
  • C and C++ also do this, which is probably why the language designers decided to make C# do it too. – Matthew Watson Jan 20 '20 at 12:00
  • @MatthewWatson hmm, I am porting (real-life) C code like my example above which has no casts and presumably compiles. – Mr. Boy Jan 20 '20 at 12:01
  • 1
    @Mr.Boy It may not need the casts, but [it will still promote unsigned shorts to ints](https://stackoverflow.com/questions/7954717/type-promotion-in-c). – Matthew Watson Jan 20 '20 at 12:05
  • 1
    @Mr.Boy C also has a bunch of conversions to magically narrow integer types, which is a constant source of confusion (and sometimes bugs) – canton7 Jan 20 '20 at 12:20
  • because operations on int are more efficient than on shorts, and it avoids overflow on many arithmetic and bitwise operations. [Why is ushort + ushort equal to int?](https://stackoverflow.com/q/10065287/995714), [byte + byte = int… why?](https://stackoverflow.com/q/941584/995714), – phuclv Jan 20 '20 at 13:06

0 Answers0