-1

So the following code

#include <stdio.h>
int main() {
  int myInt;
  myInt = 0xFFFFFFE2;
  printf("%d\n",myInt);
  return 0;
}

yields -30.

I get the idea of two's complement but when I directly type -30 I get the same number too. So my question is why would I write my number in hexadecimal form ? And if I use hexadecimal form how does the compiler distinguish between whether I mean 0xFFFFFFE2 is two's complement for -30 or the value 4294967266?

Edit: This has nothing to do with two's complement as I later on find out. Two's complement is just a design way for cpu's to operate on integers in a more efficient way. [For more information Wiki]. See @Lightness Races in Orbit 's answer for explanation of the above code.

Dot.Volare
  • 118
  • 11
  • 2
    On my compiler, with warnings enabled, it pointed out `warning: implicit conversion changes signedness: 'unsigned int' to 'int'` from the assignment. – Eljay Oct 18 '18 at 12:03

2 Answers2

7

There are some misconceptions here, all of which can be fixed by revisiting first principles:

A number is a number.

When you write the decimal literal 42, that is the number 42.

When you write the hexadecimal literal 0x2A, that is still the number 42.

When you assign either of these expressions to an int, the int contains the number 42.

A number is a number.

Which base you used does not matter. It changes nothing. Writing a literal in hex then assigning it to an int does not change what happens. It does not magically make the number be interpreted or handled or represented any differently.

A number is a number.

What you've done here is assign 0xFFFFFFE2, which is the number 4294967266, to myInt. That number is larger than the maximum value of a [signed] int on your platform, so it overflows. The results are undefined, but you happen to be seeing a "wrap around" to -30, probably due to how two's complement representation works and is implemented in your computer's chips and memory.

That's it.

It's got nothing to do with hexadecimal, so there's no "choice" to be made between hex and decimal literals. The same thing would happen if you used a decimal literal:

myInt = 4294967266;

Furthermore, if you were looking for a way to "trigger" this wrap-around behaviour, don't, because the overflow has undefined behaviour.

If you want to manipulate the raw bits and bytes that make up myInt, you can alias it via a char*, unsigned char* or std::byte*, and play around that way.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
1

Hexidecimal vs decimal has nothing at all to do with why it is displaying -30 or not.

For a 32 bit word that is being treated as signed (since you are using %d), any unsigned number that is greater than 2147483648 will be treated as a negative (2s complement number)

so, myInt could be -30, 0xFFFFFFE2, 4294967266 or -0x1E, and treating it as a signed 32 bit integer will display as -30.

lostbard
  • 5,065
  • 1
  • 15
  • 17
  • 2
    Your use of the term "will" is misleading given that [signed overflow is undefined](https://stackoverflow.com/a/16188846/560648). This is C++ not bare metal arithmetic! – Lightness Races in Orbit Oct 18 '18 at 11:58