Octal value throws compiler error but constant does not and they are the same values
This is one of those, why does it happen kind of questions. I need to take an Int32 value and "OR" it with the minimum value of its type (as a resulting of porting a 10 year old VBA application).
This breaks the compiler with a warning and an error, first the code that breaks, then the code that works and then the error message.
Breaks compiler (please disregard the name of the variable, the VBA type is long and I am using Int32):
UInt32Val = UInt32Val | 0x80000000;
This does not break the compiler:
UInt32Val = UInt32Val | Int32.MinValue;
The errors I get are as follows:
- Bitwise-or operator used on a sign-extended operand; consider casting to a smaller unsigned type first
- Cannot implicitly convert type 'long' to 'int'. An explicit conversion exists (are you missing a cast?)
It is my understanding that both 0x80000000 and Int32.MinValue equal -2147483648.
My big issue with this port is that the VBA application is using long and int which translate to .NET as Int32 and Int16 respectively, and there is a lot of bit shifting and swapping going on.
So my thinking is to make sure the size and signed property of the variables are the same to make sure I get the same values in the ported application as I do in the VBA application.
At any rate, conceptually, am I hiding a problem if I am able to f开发者_JS百科ix the compiler issue by swapping an original octal value for a constant? I'm about to run both apps and start comparing values, but I really want to understand what is happening here.
Thanks.
0x80000000 is a literal, and thus its type must be determined by the rules of C#. You haven't used a sign, and the compiler will not infer one for you, so it tries to find the smallest datatype that will fit this number as if it were positive. In this case, that's uint
, and when you |
an int
and a uint
together, the result is a long
.
In the second case, Int32.MinValue
is declared as an int
, and |
ing two int
s results in another int
.
If you want to use the literal, you can cast it first:
Int32Value = Int32Value | unchecked((int)0x80000000);
Note the unchecked
syntax: 0x80000000 would normally overflow an int
(because it's actually a positive number until those bits are stored in an int
).
精彩评论