O. Th. B.
O. Th. B.

Reputation: 1353

On narrowing casts in C# between signed and unsigned integral types

I seek to get a few thing confirmed regarding the way narrowing casts work with integral types in C# (5.0, .NET Framework 4.0/4.5). Bottom line: Can I be sure that the underlying bytes of integral types stay the same, both in order and value, when casting between signed and unsigned?

Let's say that I do the following:

short shortVal = -20000;
ushort ushortVal = (ushort)shortVal;

Now, the experiments I've done so far, shows me that the bytes in following two byte arrays:

byte[] shortBytes = BitConverter.GetBytes(shortVal);
byte[] ushortBytes = BitConverter.GetBytes(ushortVal); 

do NOT differ. I have done this exact experiment with an explicit narrowing cast from short to ushort with the value of shortVal in the range from Int16.MinValue to Int16.MaxValue. All 2^16 cases checks out fine. The actual interpreted value though, is naturally re-interpreted since the bytes stay the same. I assume the signed integral types use two's complement to represent signed values (is this true?)

I need to know, if I can count on these conversion always being "byte-safe" - as in not changing the underlying bytes and their order. This also goes for conversion the other way, from unsigned to signed. Are these conversion exact reverses of each other? I am focused mostly on short/ushort and int/uint. But all integral types are of interest.

These detail are likely up to implementation of the technology behind C# and the CLR. I am here strictly focused on the CLR for Windows 32/64 bit.

Upvotes: 1

Views: 459

Answers (1)

Honza Brestan
Honza Brestan

Reputation: 10957

This can be quite tricky.

CLR does use two's complement for signed integral number representation on x86/x64 architectures (as you observed in your test), and it's unlikely to change in the near future, because the architecture itself has good support for it. It's safe to assume it will stay like this for a while.

On the other hand, I haven't found any mention of this in either CLI or C# specifications, so you can't count on it in general, especially in face of other architectures and/or CLI implementations.

So it depends on what you want to use this on. I would stay away from depending on implementation details like this if possible, and use higher level serialization tools to convert to/from any binary representation.

Upvotes: 2

Related Questions