Bitwise operator gave me a negative number [duplicate] - c

This question already has answers here:
C bitwise negation creates negative output: [duplicate]
(3 answers)
Closed last year.
I just learned. How Bitwise operators work but when i try to use it in the c code i doesnt work.
#include <stdio.h>
int main()
{
int a = 7;
printf("%d\n", (int)~a);
return 0;
}
The expected output is 8 but it comes -8.
~0111
=
1000

Assuming int is 32 bit on your machine then 7 is 0b00000000000000000000000000000111 and ~7 becomes 0b11111111111111111111111111111000 which is -8.
Background
For signed values the most significant bit is used to determine if the value is negative or not. When the MSB is set, the value is negative.
In addition to that (char) 0b10000000 is -128 and (char) 0b11111111 is -1.
So counting works as follows:
0b10000000 0b10000001 [...] 0b11111111 0b00000000 [...] 0b01111111
-128 -127 [...] -1 0 [...] 127
That is the reason why you will get -128 when you count 127+1 and try to store that in a char.

Related

What happens when I apply the unary "-" operator to an unsigned integer? [duplicate]

This question already has answers here:
Assigning negative numbers to an unsigned int?
(14 answers)
Closed 6 years ago.
This should be a pretty simple question but I can't seem to find the answer in my textbook and can't find the right keywords to find it online.
What does it mean when you have a negative sign in front of an unsigned int?
Specifically, if x is an unsigned int equal to 1, what is the bit value of -x?
Per the C standard, arithmetic for unsigned integers is performed modulo 2bit width. So, for a 32-bit integer, the negation will be taken mod 232 = 4294967296.
For a 32-bit number, then, the value you'll get if you negate a number n is going to be 0-n = 4294967296-n. In your specific case, assuming unsigned int is 32 bits wide, you'd get 4294967296-1 = 4294967295 = 0xffffffff (the number with all bits set).
The relevant text in the C standard is in §6.2.5/9:
a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type
It will overflow in the negative direction, i.e. if your int is 16 bits x will be 65535. The bit value will be 1111111111111111 (16 ones)
If int is 32 bits, x will be 4294967295
when you apply the "-", the Two's complement of the integer is stored in variable. see here for details

Calculating 2's compliment of a number [duplicate]

This question already has answers here:
How to take twos complement of a byte in c++?
(4 answers)
Closed 6 years ago.
I was working on converting 60 to 2's complement. This is how I did:
60 to binary 00111100
1's compliment 11000011
2's compliment 11000100 (by adding 1 to the 1's compliment)
When I execute this in a program using the following piece of code
#define NUM 60
unsigned char c;
c=~NUM;
printf("%d",c);
it prints 195 not 196. Please explain the reason behind this? Also explain process of calculating (~) of any given number.
The expression ~NUM is not strictly portable. To calculate your ones complement, you could try subtracting from UCHAR_MAX instead, for example: c = UCHAR_MAX - NUM;. This will work portably because according to the standard, UCHAR_MAX is required to be a binary power minus one:
The value UCHAR_MAX shall equal 2CHAR_BIT - 1.
Don't forget to increment c afterwards, as in your final step on paper: c++.
You could safely perform the entire twos complement operation in one step, providing your underlying choice of representation is unsigned (which it should be, because the whole idea of twos complement is to represent signed integers on an unsigned group of bits): c = -NUM;. This is because negative numbers are converted to unsigned types using the following procedure also described within the C11 standard:
... if the new type is unsigned, the value is converted by repeatedly adding or subtracting one more than the maximum value that can be represented in the new type until the value is in the range of the new type.
In this case that repeatedly happens to be once: -60 + UCHAR_MAX + 1 == 196 when UCHAR_MAX == 255. If we were talking about a larger value, such as -32767 then multiple such additions would be required.
On that note, if you need to operate with numbers greater than 32768 for NUM, you'll want to think about different suffixes, for example #define NUM 32768L would be sufficient, and much larger than that #define NUM 2147483648LL.
The operator ~ performs a logical not giving back the 1's complement, not the 2's complement.
To perform the 2's complement in C use the - unary minus. See the following example:
#define NUM 60
char c1 = ~NUM; //1's complement
char c2 = -NUM; //2's complement
printf("NUM=%d, 1's complement=%d, 2's complement=%d\n",NUM, c1, c2);
But the main point is that you cannot perform a 2's complement on an unsigned type, because by default the 2's complement is used to find the representation of the same negative number. I.e. 2 -2, 10 -10, 5 -5, etc.
Consider that the values you are looking for are the unsigned representation of the negative (2's complement) value. I.e. adding:
printf("2's complementunsigned representation=%d\n", (unsigned char)c2);
Will print 196, that is -60, read as an unsigned value.
The symbol ~ calculates the 1's complement of the number. You just have to add 1 to the calculation.
c = ~NUM + 1;
Your description of the process of calculating the 1's complement is correct. To know more about it visit the wiki page on 1's complement.
Cheers!
The ~ gives you the one's complement. Use negate (-) to get the two's complement.
#include <stdio.h>
#define NUM0 0
#define NUM60 60
int main() {
unsigned char b;
unsigned char c;
b = ~NUM0;
c = -NUM0;
printf( "b=%d c=%d", b, c );
b = ~NUM60;
c = -NUM60;
printf( "b=%d c=%d", b, c );
}
outputs:
b=255 c=0
b=195 c=196

How to understand the incremented unsigned value concept? [duplicate]

This question already has answers here:
Wrap around explanation for signed and unsigned variables in C?
(4 answers)
Closed 8 years ago.
int i=~0;
uint j=(uint)i;
j++;
printf("%u",j);
I am slightly confused as before increment j is "4294967295", but after increment(j++) instead of becoming "4294967296" it is 0...can anyone please explain?
The range of 32-bit unsigned int is
0 to 4,294,967,295
So incrementing beyond this value(like +1 to this value) will lead to rolling back/wrap around to 0.
Edits:
§6.2.5 Types ¶9 A computation involving unsigned operands can never
overflow, because a result that cannot be represented by the resulting
unsigned integer type is reduced modulo the number that is one greater
than the largest value that can be represented by the resulting type
It's because it overflows, meaning the data type goes over the maximum value it can represent.
int i = ~0
All bits are set to 1. For an int, this is interpreted as -1.
uint j=(uint)i;
You copy the data and convert it to unsigned int. -1 can't be represented by an unsigned int and will similar to below wrap around so it also has all its bits set to 1.
j++;
When you add by one it overflows. It's easy to see why if you look at the addition in bits. The number is only represented by a certain number of bits, on your machine a int is 32-bit. For a 4-bit number it would look like this:
1111 + 1 = 10000
But the highest order bit has nowhere to be stored, for a unsigned integer this is defined to wrap around like this:
1111 + 1 = 0000

Bitmasking with ~0 bitshifting using variables and constants [duplicate]

This question already has answers here:
Shifting a 32 bit integer by 32 bits
(2 answers)
Closed 9 years ago.
I am currently practicing bitshifting in order to test my knowledge and cement my abilities in C, though I am currently running into a bug with C. This code represents my problem:
#include <stdio.h>
int main() {
int p = 32;
printf("%d", ~0 << 32);
printf("%d", ~0 << p);
return 0;
}
~0 << 32 is 0 (all zero bits), ~0 << p is -1 (all 1 bits). Why does C interpret these statements differently?
Because the literal 0 is of type int. When you perform ~0 you end up with a negative int. Left-shifting a negative int is undefined behavior. And left shifting past the width of an integer is also undefined behavior.
So the expected result is: anything.
Why a particular case of undefined behavior causes a certain thing to happen is nothing to dwell on or try to understand. You wrote some bugs and then the program stopped behaving in a predictable manner, simple as that.

How can 256 be represented by a char? [duplicate]

This question already has answers here:
what is char i=0x80 and why overflow did not happen in bit shifting
(6 answers)
Closed 9 years ago.
I ran the following code in xcode in to my surprise the answer was 256.
Since char is only 8 bits long i expected this to be 0.
Dumping the 1 in the 8 place.
Can someone explain what is going on?
int main()
{
unsigned char i = 0x80;
printf("%d\n", i<<1);
return 0;
}
It is being promoted to an integer, which can contain the value of 256 just fine. A cast to unsigned char will give you the result you expected:
printf("%d\n", (unsigned char)(i<<1) );
It is being promoted to an integer when you do i << 1. For example, SHL works on 32 bit words (even though your c type is 8 bit) in x86 so the shifted bit isn't discarded out of the 32 bit register. When you print this region with with "%d", you get 256. If you want to left shift with unsigned char, you can always do (i << x) & 0xff.
In this case, what is happening is that the intermediate result of i<<1 is an integer, which can represent 256.

Resources