3

How do you get the Two's complement for a int in C?

Say for example I had an int such as -254, how would I go about converting this to 100000010?

Is there any way to pull out the Two's complement value from the integer variable, as I know that in C, the ints are stored in Two's comp?

Thahleel al-Aleem
  • 711
  • 2
  • 10
  • 20
  • 4
    You need to write your own function. Here is a start http://stackoverflow.com/questions/699968/display-the-binary-representation-of-a-number-in-c – michael.schuett Mar 16 '16 at 06:29
  • 4
    "I know that in C, the ints are stored in Two's comp" - not actually guaranteed! Other representations are also allowed, such as one's complement and sign-magnitude. Two's complement is just the most common format used by modern hardware. – user2357112 Mar 16 '16 at 06:31
  • Refer following link http://stackoverflow.com/questions/21837008/how-to-convert-from-sign-magnitude-to-twos-complement – Gehan Fernando Mar 16 '16 at 06:31
  • I need it to work for the modern hardware scenario – Thahleel al-Aleem Mar 16 '16 at 06:34
  • 2
    Too bad this question is wrongly marked as a duplicate, because the linked question most certainly is not a duplicate. Also, the answers here are either confusing or misleading, in fact, the answer is simply to convert the signed integer to an unsigned integer - C guarantees that the resulting unsigned value has the same bit pattern as the two's complement representation, even on machines where integers use other representations, because the unsigned conversion is defined by adding UINT_MAX + 1 until the result is positive, which results in the two's complement bit pattern of the signed value – Remember Monica Apr 19 '19 at 18:30
  • i.e. for your 9 bit example, this would work: 0x1ffU & -254 – Remember Monica Apr 19 '19 at 18:34

4 Answers4

8

If you're operating on unsigned ints then you can invert the bits ~ and add 1 to yield the 2s complement value. x=(~y)+1; If your machine uses a 2s complement representation for signed int then this should convert (by the implementation's definition) to the proper signed int value.

The C language itself is a little vague in its guarantees in this area. To work portably on the bitwise representation of an object you should use an unsigned type.

Community
  • 1
  • 1
luser droog
  • 18,988
  • 3
  • 53
  • 105
  • As suggested in my example, the ints are signed, hence the complication – Thahleel al-Aleem Mar 16 '16 at 06:32
  • cast the variables inside the expression and cast on the way out. If its not a 2s comp machine, it won't be the right `int` but it's still "the 2s complement"...[as interpreted by the machine after the implementation-defined conversion]. – luser droog Mar 16 '16 at 06:40
  • Why would you bother using an identity like `~(unsigned)y)+1` when you could just use `0U - y`? Or unary `-(unsigned)y`. Two's complement uses the same binary operations as unsigned for add/sub (and non-widening multiply), and C already has an operator for negation. – Peter Cordes Jun 11 '21 at 12:10
  • 1
    @PeterCordes Probably only in the very rare circumstance where you want maximum portability, since C itself does not guarantee 2s complement. Or, simply to illustrate what's happening to the bits, for educational purposes. – luser droog Jun 12 '21 at 01:43
  • @luserdroog: Neither of my expressions involve C operations on signed-integer types. Two's complement `-` is the same as binary `-`, so we can do it in C with unsigned `-`. Your version relies on unsigned binary `+`, mine relies on unsigned binary `-`. Not needing separate add/sub/neg instructions (only divide, and widening multiply) is part of the reason why computers use 2's complement for signed. – Peter Cordes Jun 12 '21 at 01:46
  • 1
    I guess it makes sense to mention `1 + ~(unsigned)y` as being equivalent, via the 2's complement identity, but from other SO questions, it seems a lot of beginners get caught up in that and don't realize that it's the same as subtracting from 0. e.g. I've seen [assembly] questions where people actually used `not` / `inc` instructions instead of `neg` (on x86, a 2's complement machine), because they didn't realize that 2's complement negation is binary negation. At least in C you have a compiler to turn it back into signed `-` when compiling for 2's complement machines. – Peter Cordes Jun 12 '21 at 01:53
7

know that in C, the ints are stored in Two's comp

Not guaranteed, but in practice every computer uses two's complement.

Is there any way to pull out the Two's complement value from the integer variable

It is already in two's complement format, so it is unclear what you are asking. It would seem you are asking how to print a variable in binary format?

int data = -254;
const size_t BITS = 8*sizeof(data);
char bin_str[BITS+1];

for(unsigned int i=0; i<BITS; i++)
{
  unsigned int mask = 1u << (BITS - 1 - i);
  bin_str[i] = (data & mask) ? '1' : '0';
}
bin_str[BITS] = '\0';
Lundin
  • 195,001
  • 40
  • 254
  • 396
-1

You can convert signed-magnitude to two's complement by subtracting the number from 0x80000000 if the number is negative. This will work for a 32-bit integer on a machine using two's complement to represent negative values, but if the value is positive this will result in a two's complement negation. A right shift of a two's complement negative number will shift in one's, we can utilize this to make a mask to select between the original value, or the conversion of a signed-magnitude negative value to a two's complement negative value.

int sm2tc(int x) {
  int m = x >> 31;
  return (~m & x) | (((x & 0x80000000) - x) & m);
}

Original Code posted by Apriori

Gehan Fernando
  • 1,221
  • 13
  • 24
  • 2
    `0x80000000` is an unsigned literal so this code is bugged. Never use bitwise operators on signed types to begin with. – Lundin Mar 16 '16 at 07:32
-3

Actually, there is an easy way to do this. Simply convert your number to a binary string, and convert that string back to an integer.

Use itoa, which converts a number to its given base in string form.

http://www.cplusplus.com/reference/cstdlib/itoa/

Then, simply use the familiar atoi that converts it back to an int.