7

The piece of code is like:-

int x = -24;  
uint y = (uint) x;  
Console.WriteLine("*****" + y + "********");  
// o/p is *****4294967272********  

Why this type of behavior in C#, Detailed elaboration would be helpful. Thankyou all.

Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
codemilan
  • 1,072
  • 3
  • 12
  • 32

3 Answers3

23

Negative numbers (like -24) are represented as a binary complement, see

en.wikipedia.org/wiki/Two's_complement

for details. In your case

   24     = 00000000000000000000000000011000
  ~24     = 11111111111111111111111111100111
  ~24 + 1 = 11111111111111111111111111101000 =
          = 4294967272

When casting int to uint be careful, since -24 is beyond uint range (which [0..uint.MaxValue]) you can have OverflowException being thrown. A safier implementation is

 int x = -24;  
 uint y = unchecked((uint) x); // do not throw OverflowException exception  
Dmitry Bychenko
  • 180,369
  • 20
  • 160
  • 215
  • Correct. Works as intended. – Grisgram Mar 02 '17 at 06:39
  • The OP's code worked without the `unchecked` keyword. – Enigmativity Mar 02 '17 at 06:53
  • @Enigmativity: http://stackoverflow.com/questions/13259408/why-doesnt-c-sharp-use-arithmetic-overflow-checking-by-default – Dmitry Bychenko Mar 02 '17 at 07:04
  • 4294967295 is the max uint value can take and since 4294967272 is lower than that number it CANNOT give OverflowException so there is no need for `unchecked`. Actually casting from int to uint will never get OverflowException... – yakya Mar 02 '17 at 07:29
  • @sotn: please, carry out an easy experiment: `int x = -24; uint y = checked((uint) x);` and see the `OverflowException`. Its `-24` that's beyond `uint.MinValue` (which is `0`) – Dmitry Bychenko Mar 02 '17 at 07:34
  • @DmitryBychenko what I meant was, why to use unchecked at all (in this case) since the default option for checked/unchecked is determined by compiler option? But if it would be the opposite case (casting from uint to int, that's a different story I think) – yakya Mar 02 '17 at 07:43
  • Well It doesn't give OverflowException from uint to int either (without using checked/unchecked) :D I guess you're right.. – yakya Mar 02 '17 at 07:46
  • @DmitryBychenko - Are you saying that without the `checked` or `unchecked` then the behaviour is ambiguous (base on the compiler setting), but since the OP wants the cast to succeed then `unchecked` should be used? – Enigmativity Mar 02 '17 at 07:46
  • @sotn: imagine that you've developed the routine, tested it a pass to be build as a part of an industrial solution which has its own settings, make file, complier settings… You *don't* have the error, but users *do*, a-a-a-a! – Dmitry Bychenko Mar 02 '17 at 07:48
  • @sotn: if you want `OverflowException` on the cast *reversed*, i.e. `uint -> int`, try this: `uint y = 3000000000u; int x = checked((int) y);` since *3 billions* is within `uint` range but out of `int` one. – Dmitry Bychenko Mar 02 '17 at 08:02
  • Yes guys, you're right. I missed some points. At first I thought like the most important bit in 32 bits is used for un/signed flag whereas the other 31 bits are used for the value and thought that the numbers greater than 2^31 cannot be handled by `int` data type since it will require to not use that most important bit flag and I thought that the numbers between 0 and -(2^31) are ok to convert bidirectionally since it doesn't "compromise" that sign flag. I don't know if it makes sense but I was wrong :) – yakya Mar 02 '17 at 08:19
  • Thanks @DmitryBychenko, this is the detailed answer I needed. Thankyou again. – codemilan Mar 02 '17 at 12:43
11

There are few ways to convert int to uint

int x;

Technique #1

uint y = Convert.ToUInt32(x);

Technique #2

uint y = checked((uint) x);

Technique #3

uint y = unchecked((uint) x);

Technique #4

uint y = (uint) x;
Sachith Wickramaarachchi
  • 5,546
  • 6
  • 39
  • 68
-2

Try the below code

int x = -24;  
Console.WriteLine("*****" + Convert.ToUInt32(x) + "********");
Siby Sunny
  • 714
  • 6
  • 14