Unwrapped overflowed integer values in C# where large negative integers overflow and appear as negative values.
You may find that when working with large integer values that these numbers suddenly become negative numbers.
This can be seen in the PowerShell registry editor and also in some SNMP MIBs. The reason why this happens is simple.
The last bit of a signed integer determines whether the number is negative or positive, whereas on an unsigned integer this bit is part of the number and therefore the number can be twice as big.
UInt32.MaxValue = 4294967295
11111111111111111111111111111111
Int32.MaxValue = 2147483647
01111111111111111111111111111111
The problem of wrapping occurs when you exceed 2147483647 - lets say 2147483648 which converts in bits as the following
10000000000000000000000000000000
This works fine in a UInt32, however if you just take these bits and stick them in an Int32 the bits fit (there are still 32 bits available) however the value returns as -2147483648 because the negative values are working backwards this is the "highest" negative value.
If we put the highest UInt32 value 4294967295 the Int32 interprets this as negative but because all the flags are set it returns the "lowest" number it can before zero which is -1.
11111111111111111111111111111111
Simply converting the number from the wrapped signed integer will cause an overflow exception
UInt32 value = Convert.ToUInt32(-1);
System.OverflowException: 'Value was either too large or too small for a UInt32.'
Instead transfer the bits to a byte array and them convert the bits to an unsigned integer and they will remain in the correct places.
This can be seen in the PowerShell registry editor and also in some SNMP MIBs. The reason why this happens is simple.
The last bit of a signed integer determines whether the number is negative or positive, whereas on an unsigned integer this bit is part of the number and therefore the number can be twice as big.
UInt32.MaxValue = 4294967295
11111111111111111111111111111111
Int32.MaxValue = 2147483647
01111111111111111111111111111111
The problem of wrapping occurs when you exceed 2147483647 - lets say 2147483648 which converts in bits as the following
10000000000000000000000000000000
This works fine in a UInt32, however if you just take these bits and stick them in an Int32 the bits fit (there are still 32 bits available) however the value returns as -2147483648 because the negative values are working backwards this is the "highest" negative value.
If we put the highest UInt32 value 4294967295 the Int32 interprets this as negative but because all the flags are set it returns the "lowest" number it can before zero which is -1.
11111111111111111111111111111111
Simply converting the number from the wrapped signed integer will cause an overflow exception
UInt32 value = Convert.ToUInt32(-1);
System.OverflowException: 'Value was either too large or too small for a UInt32.'
Instead transfer the bits to a byte array and them convert the bits to an unsigned integer and they will remain in the correct places.
/// <summary>
/// Unwraps the specified integer value.
/// </summary>
/// <param name="value">The integer value to unwrap - for example 36, or -1.</param>
/// <returns>The unwrapped unsigned integer from the specified integer value.</returns>
public static UInt32
UnwrapInteger(Int32 value)
{
return BitConverter.ToUInt32(BitConverter.GetBytes(value), 0);
}
Comments
Post a Comment