Using bit mask to convert a signed integer into two's complement - c

I am given this code to convert a signed integer into two's complement but I don't understand how it really works, especially if the input is negative.
void convertB2T( int32_t num) {
uint8_t bInt[32];
int32_t mask = 0x01;
for (int position = 0; position < NUM_BITS; position++) {
bInt[position] = ( num & Mask) ? 1 : 0;
Mask = Mask << 1;
}
}
So my questions are:
num is an integer, Mask is a hex, so how does num & Mask work? Does C just convert num to binary representation and do the bitwise and? Also the output of Mask is an integer correct? So if this output is non-zero, it is treated as TRUE and if zero, FALSE, right?
How does this work if num is negative? I tried running the code and actually did not get a correct answer (all higher level bits are 1's).

This program basically extracts each bit of the number and puts it in a vector. So every bit becomes a vector element. It has nothing to do with two's complement conversion (although the resulting bit-vector will be in two's complement, as the internal representation of numbers is in two's complement).
The computer has no idea what hex means. Every value is stored in binary, because binary is the only thing computer understands. So, ,the "integer" and the hex values are converted to binary (the hex there is also an integer). On these binary representations that the computer uses, the binary operators are applied.
In order to understand what is happening with the result when num is negative, you need to understand that the result is basically the two's complement representation of num and you need to know how the two's complement representation works. Wikipedia is a good starting point.

To answer your questions
1.Yes num is integer represented in decimal format and mask is also integer represented in hex format.
Yes C compiler treats num and mask with their binary equivalents.
Say
num = 24; // binary value on 32 bit machine is 000000000000000000011000
mask = 0x01; // binary value on 32 bit machine is 000000000000000000000001
Yes compiler now performs & bitwise and the equivalent binary values.
Yes if output is nonzero, treated as true
If a number is negative, its represented in 2's complement form.
Basically your code is just storing binary equivalent of number into array. You are not representing in twos complement.
If MSB is 1 indicates number is negative. if a number is negative
num = -24; // represent binary value of 24
000000000000000000011000 -> apply 1's complement + 1 to this binary value
111111111111111111100111 -> 1's complement
+000000000000000000000001 -> add 1
------------------------
111111111111111111101000 -> -24 representation
------------------------

Related

Objective C Int to 2's Complement Conversion

I'm trying to convert my 16 bit integer to two's complement if it's negative.
At the moment, I'm using the One's complement operator. I figure I can use that, and then add 1 to the binary value to convert it to two's complement. However, I'm unable to do x = ~a + 1 because that just yields the integer value + 1.
If my process is correct, how can I add 1 to the binary integer? If not, what is the most appropriate way to convert a 16 bit integer to 2's complement in Objective-C?
A two's complement is a kind of representation of signed numbers, not a value or an operation. On nearly all modern computers two's complements are the standard representation of signed integers. (And it is one of three allowed representations of integers in the standard.)
Therefore if you have any signed integral number, it is represented in two's complement. I think you want to have "the" two's complement of a positive number. This is simply the negative value, if your machine uses two's complements for signed numbers.
int positiveValue = 5;
int twosComplement = -positiveValue;

How to get two's complement of an int in C? [duplicate]

This question already has answers here:
Display the binary representation of a number in C? [duplicate]
(8 answers)
Closed 6 years ago.
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?
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.
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';
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
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.

C programming bitfield in structure

Why is answer of it
-1, 2, -3 ? (especially -3 ??? how come)
struct b1 {
int a:1;
int b:3;
int c:4;
} ;
int main()
{
struct b1 c = {1,2,13};
printf("%d, %d, %d",c.a,c.b,c.c);
return 0;
}
Compiled on VC++ 32 bit editor. Many Thanks.
signed integers are represented in twos complement. The range of a 1-bit twos complement number is -1 to 0. Because the first bit of a twos complement number indicates it is negative, which is what you have done there.
See here:
sign extend 1-bit 2's complement number?
That is the same for the third number, you have overflowed the range of -8 to 7 which is the range of a 4 bit signed integer.
What you meant to do there is make all of those int -> unsigned int
See here for twos complement explanation:
http://www.ele.uri.edu/courses/ele447/proj_pages/divid/twos.html
Because a and c are signed integers with their sign bit set, hence they are negative:
a: 1d = 1b (1 bit)
b: 2d = 010b (3 bits)
c: 13d = 1101b (4 bits)
Signed integer values are stored in two's complement, with the highest bit representing the sign (1 means "negative"). Hence, when you read the bitfield values as signed int's, you get back negative values for a and c (sign extended and converted back from their two's complement representation), but a positive 2 for b.
To get the absolute value of a negative two's complement number, you subtract one and invert the result:
1101b
-0001b
======
1100b
1100b inverted becomes 0011b which is equal to 3d. Since the sign bit is negative (which you had to examine before doing the previous calculation anyway), the result is -3d.

How negative numbers are stored in memory? How to know the bit representation?

I am aware of MSB, LSB, sign and magnitude one's and two's complement etc. Now, I would like to know if I am writing and program which does some bit manipulation, How would I check the actual bit level data in memory?
i.e. int a = -1; How would I know if it is 1001 or 1110 or 1111 in a 4-bit representation?
How do I figure out the method my implementation uses to represent negative numbers?
I am looking for some way to examine the bit level data of a C program.
My current platform is Ubuntu 12.04 LTS. Once again, the question is not about how it is done. It is about how to find out or justify that it is done in some way.
union { int i; unsigned u; } x;
x.i = -1;
Now x.u gives you the unsigned integer with the same bits. There is only one way to represent unsigned numbers so you can just examine that. (As a hint: it is most likely two's complement.)
printf("%x\n", x.u);
The above print statement will print out the hexadecimal representation of the unsigned integer, which you can use to determine the bits.
One easy method is to inspect the variable in a debugger like this:
(gdb) p/t var
p/t says to print the binary representation.
void showBit(int num, int nBit)//nBit -> number of bits
{
unsigned int temp = 1<<(nBit-1), i;
for(i=0; i<nBit; ++i)
{
printf("%d ", ((num&temp)?1:0) );
temp = temp>>1;
}
printf("\n");
}
you can use this function to print the binary representation. see it on ideone.
By applying bitwise operations. E.g. you can test if the n-th bit is set by performing a & (1<<n) (apply it in a loop, then you got the whole number).
EDIT: But this does only work, when the internal representation is binary. When a different system (e.g. the Russians had in the ´70s a computer with ternary logic and number system, and the Polish a system on negabinary basis) is used this will not give the right internal used format.
In C, negative numbers are expressed in a 2's compliment format for signed numbers.
This is done, to avoid any compiler(I,e it works even if int is 8 bit or 16 bit or 32 bit and so on).
In your case if you compiler interprets int as 8 bit then 1111 1111 will be stored. As soon as the first bit(sign bit) is 1 compiler understands that it is a negative number and understands the number has to be the two's compliment. which is nothing but 0000 0001, with a negative sign
You can even make the use of union.
union num
{
int f;
char c[4];
};
void printBinary(union num u)
{
int i,t,j;
for(i=sizeof(u)-1; i>=0; i--)
{
for(j=0,t=128; j<8; j++,t>>=1)
printf("%d",(u.c[i]&t)?1:0);
printf(" ");
}
}
int main()
{
union num n;
n.f=10;
printBinary(n);
return 0;
}
see here: http://ideone.com/i9YCt
How do I figure out the method my implementation uses to represent negative numbers?
Here is how:
unsigned int a = -1;
swicth (a & 3U)
{
case 3:
printf("two's complement\n");
break;
case 2:
printf("one's complement\n");
break;
case 1:
printf("sign and magnitude\n");
break;
default:
printf("compiler broken\n");
break;
}
The ultimate answer is actually in your compiler documentation which is required to document which signed representation is used. For example, for gcc:
Whether signed integer types are represented using sign and magnitude, two's complement, or one's complement, and whether the extraordinary value is a trap representation or an ordinary value (C99 6.2.6.2)
GCC supports only two's complement integer types, and all bit patterns are ordinary values
http://gcc.gnu.org/onlinedocs/gcc/Integers-implementation.html
The positive and negative numbers identified by the 8th bit of the number. if 8th bit is 0 it is positive otherwise negative.
For example x=8
so In binary x=8=0000 1000 (It is positive number, so eight bit is 0 from right to left)
For negative x = -8
The negative numbers are represented in binary using 2's complement usually.
so x = -8
step 1 binary of 8 = 0000 1000
step 2 1's complement = 1111 0111
step 3 2's complement = 1
y = 1111 1000 =248(so it represents the negative because 8th bit is 1 then it follows the below formula)
The formula for getting negative value from binary representation is 2^8-y
so 256-248=8

Clarification is needed on bitwise not (~) operator

Suppose you have the following C code.
unsigned char a = 1;
printf("%d\n", ~a); // prints -2
printf("%d\n", a); // prints 1
I am surprised to see -2 printed as a result of ~1 conversion:
The opposite of 0000 0001 is 1111 1110. That is anything but -2.
What am I missing here?
It is two's complement.
In two's complement representation, if a number x's most significant bit is 1, then the actual value would be −(~x + 1).
For instance,
0b11110000 = -(~0b1111 + 1) = -(15 + 1) = -16.
This is a natural representation of negative numbers, because
0000001 = 1
0000000 = 0
1111111 = -1 (wrap around)
1111110 = -2
1111101 = -3 etc.
See http://en.wikipedia.org/wiki/Two%27s_complement for detail.
BTW, to print an unsigned value, use the %hhu or %hhx format. See http://www.ideone.com/YafE3.
%d stands for signed decimal number, not unsigned. So your bit pattern, even though it is stored in an unsigned variable, is interpreted as a signed number.
See this Wikipedia entry on signed number representations for an understanding of the bit values. In particular see Two's complement.
One (mildly humorous) way to think of signed maths is to recognize that the most significant bit really represents an infinite number of bits above it. So in a 16-bit signed number, the most significant bit is 32768+65536+131072+262144+...etc. which is 32768*(1+2+4+8+...) Using the standard formula for a power series, (1+ X + X^2 + X^3 +...) = 1/(1-X), one discovers that (1+2+4+8+...) is -1, so the sum of all those bits is -32768.

Resources