Can't assign 32bit hexadecimal value to integer - c#

First, this question has related posts:
Why Int32 maximum value is 0x7FFFFFFF?
However, I want to know why the hexadecimal value is always treated as an unsigned quantity.
See the following snippet:
byte a = 0xFF; //No error (byte is an unsigned type).
short b = 0xFFFF; //Error! (even though both types are 16 bits).
int c = 0xFFFFFFFF; //Error! (even though both types are 32 bits).
long d = 0xFFFFFFFFFFFFFFFF; //Error! (even though both types are 64 bits).
The reason for the error is because the hexadecimal values are always treated as unsigned values, regardless of what data-type they are stored as. Hence, the value is 'too large' for the data-type described.
For instance, I expected:
int c = 0xFFFFFFFF;
To store the value:
-1
And not the value:
4294967295
Simply because int is a signed type.
So, why is it that the hexadecimal values are always treated as unsigned even if the sign type can be inferred by the data-type used to store them?
How can I store these bits into these data-types without resorting to the use of ushort, uint, and ulong?
In particular, how can I achieve this for the long data-type considering I cannot use a larger signed data-type?

What's going on is that a literal is intrinsically typed. 0.1 is a double, which is why you can't say float f = 0.1. You can cast a double to a float (float f = (float)0.1), but you may lose precision. Similarly, the literal 0xFFFFFFFF is intrinsically a uint. You can cast it to an int, but that's after it has been interpreted by the compiler as a uint. The compiler doesn't use the variable to which you are assigning it to figure out its type; its type is defined by what sort of literal it is.

They are treated as unsigned numbers, as that is what the language specification says to do

Related

ANSI character handling by C and C#

I have a character '¿'. If I cast it with integer in C, result is -61 and same casting in C#, result is 191. Can someone explain me the reason.
C Code
char c = '¿';
int I = (int)c;
Result I = -62
C# Code
char c = '¿';
int I = (int)c;
Result I = 191
This is how singed/unsigned numbers are represented and converted.
It looks like C compiler's default in your case use signed byte as underlying type for char (since you are note explicitly specifying unsigend char compiler's default is used, See - Why is 'char' signed by default in C++? ).
So 191 (0xBF) as signed byte means negative number (most significant bit is 1) - -65.
If you'd use unsigned char value would stay positive as you expect.
If your compiler would you wider type for char (i.e. short) that 191 would stay as positive 191 irrespective of whether or not char is signed or not.
In C# where it always unsigned - see MSDN char:
Type: char
Range: U+0000 to U+FFFF
So 191 will always convert to to int as you expect.

Is there an easy way to convert from 32bit integer to 16bit integer?

I have a 32 bit int and I want to address only the lower half of this variable. I know I can convert to bit array and to int16, but is there any more straight forward way to do that?
It you want only the lower half, you can just cast it: (Int16)my32BitInt
In general, if you're extending/truncating bit patterns like this, then you do need to be careful about signed types - unsigned types may cause fewer surprises.
As mentioned in the comments - if you've enclosed your code in a 'checked' context, or changed your compiler options so that the default is 'checked', then you can't truncate a number like this without an exception being thrown if there are any non-zero bits being discarded - in that situation you'd need to do:
(UInt16)(my32BitInt & 0xffff)
(The option of using signed types is gone in this case, because you'd have to use & 0x7fff which then preserves only 15 bits)
just use this function
Convert.ToInt16()
or just
(Int16)valueasint
You can use implicit conversation to Int16 like;
(Int16)2;
but be careful when you do that. Because Int16 can't hold all possible Int32 values.
For example this won't work;
(Int16)2147483683;
because Int16 can hold 32787 as maximum value. You can use unchecked (C# Reference) keyword such this cases.
If you force an unchecked operation, a cast should work:
int r = 0xF000001;
short trimmed = unchecked((short) r);
This will truncate the value of r to fit in a short.
If the value of r should always fit in a short, you can just do a normal cast and let an exception be thrown.
If you need a 16 bit value and you happen to know something specific like that the number will never be less than zero, you could use a UINT16 value. That conversion looks like:
int x = 0;
UInt16 value = (UInt16)x;
This has the full (positive) range of an integer.
Well, first, make sure you actually want to have the value signed. uint and ushort are there for a reason. Then:
ushort ret = (ushort)(val & ((1 << 16) - 1));

How do I cast a 16 bit 'short' into a 32-bit integer in C#?

I have a 16 bit signed number coming in from hardware. I want to caste it into an Int32.
When I cast it as a short, it works occasionally when the number is negative. Most of the time however, I get a first chance exception of type 'System.OverflowException' occurred.
Here is my code:
int M1;
M1 = (short)(INBuffer[3] << 8) + INBuffer[2];
How do I cast a 16 bit short to a 32 bit integer in C#?
Assuming INBuffer is a byte array, you can safely cast to a ushort but not a short. This is because if the highest bit of the higher order byte is 1, the value is too large for a signed short once it is bitshifted.
In your case, if you want an int, no need to cast at all - the bit shift outputs an int, and the addition of a byte again leaves an int - you're already there...

C# int byte conversion [duplicate]

This question already has answers here:
Integer summing blues, short += short problem
(5 answers)
Closed 6 years ago.
Why is
byte someVar;
someVar -= 3;
valid but
byte someVar;
someVar = someVar - 3;
isnt?
Surprisingly, when you perform operations on bytes the computations will be done using int values, with the bytes implicitly cast to (int) first. This is true for shorts as well, and similarly floats are up-converted to double when doing floating-point arithmetic.
The second snippet is equivalent to:
byte someVar;
someVar = (int) someVar - 3;
Because of this you must cast the result back to (byte) to get the compiler to accept the assignment.
someVar = (byte) (someVar - 3);
Here's a copy of a table in the CLI specification (Ecma 335) that specifies which operands are valid on the binary numeric operators of the type A op B, where A and B are the operands and "op" is the operator, like Opcodes.Sub that you are using in your snippet:
Some annotations are required with this:
"native int" is IntPtr in a C# program
F represents a floating point type, double or float in C#
& represents a pointer value, the boxes are shaded because they are unsafe operations
O represents an object reference
x is an operation that's not permitted.
Note the row and column for F, both operands must be floating point, you cannot directly add, say, an int to a double. The C# compiler deals with that limitation by automatically converting the int operand to double so that the operator is valid.
Relevant to your question: also note that the byte, sbyte, char, short and ushort types are not present. Same approach, the compiler converts the operands to the smallest type that can represent the value so that the operator can be used. Which will be int32. According to the table, the result of the operation will be int32.
Now here's the rub: the result is int32 but assigning that back to a byte value requires a narrowing conversion. From 32 bits to 8 bits. That's trouble because it loses significant bits. The C# compiler requires you to make that explicit. You essentially acknowledge that you know what you're doing and that you are aware of the potentially surprising result. Like this one:
byte v = 255;
v = (byte)(v + 1);
The -= operator is a problem because there is no effective way to apply that required cast. It isn't expressible in the language syntax. Using (byte)3 doesn't make sense, the literal gets converted to int32 anyway to make the operator work.
They punted the problem, the compiler automatically emits the cast without your help.

Why is a cast required for byte subtraction in C#? [duplicate]

This question already has answers here:
byte + byte = int... why?
(16 answers)
Closed 9 years ago.
I have to following code in VS2008 .net 3.5 using WinForms:
byte percent = 70;
byte zero = 0;
Bitmap copy = (Bitmap)image1.Clone();
...
Color oColor = copy.GetPixel(x, y);
byte oR = (byte)(oColor.R - percent < zero ? zero : oColor.R - percent);
When I leave the "(byte)" off the last line of code, I get a compiler error saying it "Cannot implicitly convert type 'int' to 'byte'." If everything is of type byte and byte is an integer type... then why do I need to have the cast?
Because subtraction is coercing up to an integer. As I recall, byte is an unsigned type in C#, so subtraction can take you out of the domain of bytes.
That's because the result of a byte subtraction doesn't fit in a byte:
byte - byte = (0..255) - (0..255) = -255..255
Arithmetic on bytes results in an int value by default.
Because arithmetic on bytes returns integers by default so of the two possible assignments the narrower type of zero (byte) is promoted to int (that of oColor.r - percent). Thus the type of the operation is an int. The compiler will not, without a cast, allow you to assign a wider type to a narrower type, because it's a lossy operation. Hence you get the error, unless you explicitly say "I know I'm losing some data, it's fine" with the cast.
This is because byte subtraction returns an int. Actually any binary arithmetic operations on bytes will return an int, so the cast is required.
Because arithmetic operations on sbyte, byte, ushort, and short are automatically converted to int. The most plausible reason for this is that such operations are likely to overflow or underflow.
Thus, in your ternary operation, the final oColor.R - percent, actually results in an int, not a byte. So the return type of the operation is int.
Because the arithmetic expression on the right-hand side of the assignment operator evaluates to int by default. In your example percent defaults to int. You can read more about it on the MSDN page.
Try to run this C# code:
object o = (byte)(1);
o = (int)o;
What do you expect? Now try :)
I think this is right:
Eric Lippert says, "I don't think of bytes as "numbers"; I think of them as patterns of bits that could be interpreted as numbers, or characters, or colors or whatever. If you're going to be doing math on them and treating them as numbers, then it makes sense to move the result into a data type that is more commonly interpreted as a number."
Perhaps byte is closer to char than to int.
FWIW, java also promotes bytes to int.

Categories