Bits representation of negative numbers - c

This is a doubt regarding the representation of bits of signed integers. For example, when you want to represent -1, it is equivalent to 2's complement of (+1). So -1 is represented as 0xFFFFFFF. Now when I shift my number by 31 and print the result it is coming back as -1.
signed int a = -1;
printf(("The number is %d ",(a>>31));//this prints as -1
So can anyone please explain to me how the bits are represented for negative numbers?
Thanks.

When the top bit is zero, the number is positive. When it's 1, the number is negative.
Negative numbers shifted right keep shifting a "1" in as the topmost bit to keep the number negative. That's why you're getting that answer.
For more about two's complement, see this Stackoverflow question.
#Stobor points out that some C implementations could shift 0 into the high bit instead of 1. [Verified in Wikipedia.] In Java it's dependably an arithmetic shift.
But the output given by the questioner shows that his compiler is doing an arithmetic shift.

The C standard leaves it undefined whether the right shift of a negative (necessarily signed) integer shifts zeroes (logical shift right) or sign bits (arithmetic shift right) into the most significant bit. It is up to the implementation to choose.
Consequently, portable code ensures that it does not perform right shifts on negative numbers. Either it converts the value to the corresponding unsigned value before shifting (which is guaranteed to use a logical shift right, putting zeroes into the vacated bits), or it ensures that the value is positive, or it tolerates the variation in the output.

This is an arithmetic shift operation which preserves the sign bit and shifts the mantissa part of a signed number.
cheers

Basically there are two types of right shift. An unsigned right shift and a signed right shift. An unsigned right shift will shift the bits to the right, causing the least significant bit to be lost, and the most significant bit to be replaced with a 0. With a signed right shift, the bits are shifted to the right, causing the least significant bit be be lost, and the most significant bit to be preserved. A signed right shift divides the number by a power of two (corresponding to the number of places shifted), whereas an unsigned shift is a logical shifting operation.
The ">>" operator performs an unsigned right shift when the data type on which it operates is unsigned, and it performs a signed right shift when the data type on which it operates is signed. So, what you need to do is cast the object to an unsigned integer type before performing the bit manipulation to get the desired result.

Have a look at two's complement description. It should help.

EDIT: When the below was written, the code in the question was written as:
unsigned int a = -1;
printf(("The number is %d ",(a>>31));//this prints as -1
If unsigned int is at least 32 bits wide, then your compiler isn't really allowed to produce -1 as the output of that (with the small caveat that you should be casting the unsigned value to int before you pass it to printf).
Because a is an unsigned int, assigning -1 to it must give it the value of UINT_MAX (as the smallest non-negative value congruent to -1 modulo UINT_MAX+1). As long as unsigned int has at least 32 bits on your platform, the result of shifting that unsigned quantity right by 31 will be UINT_MAX divided by 2^31, which has to fit within int. (If unsigned int is 31 bits or shorter, it can produce whatever it likes because the result of the shift is unspecified).

Related

K&R C chapter 2 assignment operators and expressions

Assignment operators are not something I expected to struggle with. Everything in this section so far is familiar, but the way they explain it makes it seem foreign. I think it's the bitwise operators I'm confused about.
Anyway here is the part I don't get.
The function bitcount counts the number of 1-bits in its integer argument.
/*bitcount: count 1 bits in x */
int bitcount (unsigned x)
{
int b;
for(b=0; x != 0; x >>= 1) {
if(x & 01)
b++;
return b;
}
Declaring the argument x to be unsigned ensures that when it is right-shifted, vacated bits will be filled with zeros, not sign bits, regardless of the machine the program is run on.
Not that I really understand the code, but this last sentence is confusing me the most. What does this mean? Does it mean "ones" by "sign bits" and does this have to do with twos complement?
I really had trouble getting through the bitwise operations. Can anyone recommend some comprehensive material to supplement the bitwise stuff in this book?
Suppose x is two’s complement. For illustration, let‘s use an eight-bit width. (C always shifts in a wider width, at least that of int.)
If x is 64 (010000002) and we shift it right one bit, we get 32 (001000002). When we repeat that, we get 16 (000100002), 8 (000010002), 4 (000001002), 2 (000000102) , and 1 (000000012).
When x is −64, two’s complement represents it with 110000002. If we shift that right and bring in a 0 bit, the bits are 011000002, which represents 64+32 = 96. So −64 becomes 96. Now, that might be fine if one were just working with bits. But, if we want to use bit-shifting to divide numbers, we want −32, not 96. The bits for −32 are 111000002. So we can get that by bring in a 1 bit instead of a 0 bit. And the bits for −16 are 111100002. Then −8, −4, −2, and −1 are 111110002, 111111002, 111111102, 111111112. In each case, we bring in a 1 bit when shifting.
So, if we want to use bit-shifting for division, there is a simple rule for a one-bit shift: Shift all bits right one spot and leave the sign bit as is (0 or 1). If we are shifting more than one bit, keep copying the sign bit.
That is called an arithmetic right shift. So, we have two kinds of right shift: An arithmetic right shift that copies the sign bit, and a logical right shift that brings in 0 bits.
For unsigned types, the C standard says a right shift is logical.
For signed types, the C standard does not say whether it is arithmetic or logical. It leaves it to the implementation to define which that implementation uses (or possibly to define something else). That might be due to the history; early machines might not have provided arithmetic right-shift instructions (and may not even have used two’s complement), although it seems hard to imagine these days.
So, when you are writing code that shifts right and you want to be sure of the result you will get, you can use an unsigned type to be sure to get a logical shift.
In twos complement representation the highest order bit is reserved for the sign. The highest order bit is 0 for positive numbers and 1 for negative numbers.
If you right shift the bits of a negative number the 1 originally in the highest order bit will be shifted to the next lower order bit, eventually ending up in the lowest order bit if you keep shifting the bits.
In the code the for loop shifts the bits of x by one bit position and assigns the shifted value to x.
for (b = 0; x != 0; x >>=1 )
First b, which is used to count the number of 1 bits in the number is set to 0.
The condition to continue the loop is x != 0. When all the 1 bits are shifted out of x the only thing left will be 0 bits. x will then equal 0.
The operation performed after each iteration is to right-shift the value in x by 1.
The if condition in the body of the loop performs bit-wise AND operation on x. The bit mask has a value of 1, which is an instance of the int value with all bits 0 except the lowest order bit. That AND operation will evaluate to 1 (or true in C) if the lowest order bit is 1, and to 0 (or false in C) if the lowest order bit is 0. The count of one bits is incremented if the if condition is true.

short int Integer wrap around / short int inversion in c not understood, difference between assignment and prints

The following code fragment
short int k = -32768;
printf("%d \n", -k);
k=-k;
printf("%d \n", k);
prints
32768
-32768
I would assume that both prints are equal.
Can somebody explain what the difference is and why the assignment k=-k causes a wrap around? It was hard to find a explanation online, as i don't really know what to google.
Well, to print a short, you need to use a length modifier.
Change the format string to %hd.
Because SHRT_MIN = -32768 and SHRT_MAX = +32767. Check out how 2's complement work.
Edit
Actually, according to the international standard of the C programming language (i.e. Committee Draft — May 6, 2005, pp. 50-51) regarding signed integers:
For signed integer types, the bits of the object representation shall be divided into three groups: value bits, padding bits, and the sign bit.
There need not be any padding bits; there shall be exactly one sign bit.
Each bit that is a value bit shall have the same value as the same bit in the object representation of the corresponding unsigned type (if there are M value bits in the signed type and N in the unsigned type, then M <= N).
If the sign bit is zero, it shall not affect the resulting value.
If the sign bit is one, the value shall be modified in one of the following ways:
the corresponding value with sign bit 0 is negated (sign and magnitude);
the sign bit has the value −(2N ) (two's complement);
the sign bit has the value −(2N − 1) (ones' complement).
Which of these applies is implementation-defined, as is whether the value with sign bit 1 and all value bits zero (for the first two), or with sign bit and all value bits 1 (for ones' complement), is a trap representation or a normal value. In the case of sign and magnitude and ones' complement, if this representation is a normal value it is called a negative zero.
So, in other words, in your case it's seems that 2's complement is being used, but this should not be assumed to be in all platforms and compilers.
-32768 is 8000 in hexadecimal notation. 32768 can not be represented as a signed 16 bit number, therefore the compiler promotes -k to an int with the hex value 00008000. When this number is assigned to the 16-bit variable, the high bits are truncated, resulting in 8000 or -32768 again.

Right shifting in c programming.

Consider the expression x>>y , here x is signed int with left most bit is 1 then is the result depend on machine ?
I have tried for signed int with left most bit is 0 i got same result, but i don't know about given case.
There are no unambiguous "leftmost" or "rightmost" bits (which depends on convention), but most significant and least significant bits. The sign bit on a 2's complement machine is the most significant bit.
>> uses zero extension if the shifted is an unsigned.
Positive signed values behave like positive unsigned values. The >> of a negative quantity, however, is implementation defined, but wherever I have used it, negative numbers have been sign-extended.
Also, left-shifting something to the sign bit of a signed quantity is undefined behaviour, so for most portable programs it is best to use bitshift tricks only to unsigned values.

C what happens in the compiler when -1 is assigned to an unsigned short or uint16_t? [duplicate]

I was goint through k & r. I was having problem in understanding following lines on page 197(section A6)
Integral conversions: any integer is
converted to a given unsigned type by
finding the smallest non negative
value that is congruent to that
integer,modulo one more than the
largest value that can be represented
in the unsigned type.
Can any body explain this in a bit detail.
Thanks
It means only low value bits will be count and high order bits will be discarded.
For example:
01111111 11111111 11110000 00001111
when converted to a 16 bit unsigned short will be:
11110000 00001111
This is effectively mathematically expressed in:
target_value = value % (target_type_max+1) ( % = modulus operator )
any integer is converted to a given unsigned type by finding the smallest non negative value that is congruent to that integer,modulo one more than the largest value that can be represented in the unsigned type.
Let's take this bit by bit and from backwards:
What is the largest value that can be represented in the unsigned type of width n bits?
2^(n) - 1.
What is one more than this value?
2^n.
How does the conversion take place?
unsigned_val = signed_val % 2^n
Now, the why part: The standard does not mandate what bit representation is used. Hence the jargon. In a two's complement representation -- which is by far the most commonly used -- this conversion does not change the bit pattern (unless there is a a truncation, of course).
Refer to Integral Conversions from the Standard for further details.

negative integer number >> 31 = -1 not 1? [duplicate]

This question already has answers here:
Arithmetic bit-shift on a signed integer
(6 answers)
Closed 9 years ago.
so, lets say I have a signed integer (couple of examples):
-1101363339 = 10111110 01011010 10000111 01110101 in binary.
-2147463094 = 10000000 00000000 01010000 01001010 in binary.
-20552 = 11111111 11111111 10101111 10111000 in binary.
now: -1101363339 >> 31 for example, should equal 1 right? but on my computer, I am getting -1. Regardless of what negative integer I pick if x = negative number, x >> 31 = -1. why? clearly in binary it should be 1.
Per C99 6.5.7 Bitwise shift operators:
If E1 has a signed type and a negative value, the resulting value is implementation-defined.
where E1 is the left-hand side of the shift expression. So it depends on your compiler what you'll get.
In most languages when you shift to the right it does an arithmetic shift, meaning it preserves the most significant bit. Therefore in your case you have all 1's in binary, which is -1 in decimal. If you use an unsigned int you will get the result you are looking for.
Per C 2011 6.5.7 Bitwise shift operators:
The result of E1 >> E2 is E1 right-shifted E2 bit positions. If E1 has an unsigned type
or if E1 has a signed type and a nonnegative value, the value of the result is the integral
part of the quotient of E1/ 2E2. If E1 has a signed type and a negative value, the
resulting value is implementation-defined.
Basically, the right-shift of a negative signed integer is implementation defined but most implementations choose to do it as an arithmetic shift.
The behavior you are seeing is called an arithmetic shift which is when right shifting extends the sign bit. This means that the MSBs will carry the same value as the original sign bit. In other words, a negative number will always be negative after a left shift operation.
Note that this behavior is implementation defined and cannot be guaranteed with a different compiler.
What you are seeing is an arithmetic shift, in contrast to the bitwise shift you were expecting; i.e., the compiler, instead of "brutally" shifting the bits, is propagating the sign bit, thus dividing by 2N.
When talking about unsigned ints and positive ints, a right shift is a very simple operation - the bits are shifted to the right by one place (inserting 0 on the left), regardless of their meaning. In such cases, the operation is equivalent to dividing by 2N (and actually the C standard defines it like that).
The distinction comes up when talking about negative numbers. Several negative numbers representation exist, although currently for integers most commonly 2's complement representation is used.
The problem of a "brutal" bitwise shift here is, for starters, that one of the bits is used in some way to express the sign; thus, shifting the binary digits regardless of the negative integers representation can give unexpected results.
For example, commonly in 2's representation the most significant bit is 1 for negative numbers, 0 for positive numbers; applying a bitwise shift (with zeroes inserted to the left) to a negative number would (between other things) make it positive, not resulting in the (usually expected) division by 2N
So, arithmetic shift is introduced; negative numbers represented in 2's complement have an interesting property: the division by 2N behavior of the shift is preserved if, instead of inserting zeroes from the left, you insert bits that have the same value of the original sign bit.
In this way, signed divisions by 2N can be performed with just a bit of extra logic in the shift, without having to resort to a fully-fledged division routine.
Now, is arithmetic shift guaranteed for signed integers? In some languages yes1, but in C it's not like that - the behavior of the shift operators when dealing with negative integers is left as an implementation-defined detail.
As often happens, this is due to different hardware support for the operation; C is used on vastly different platforms, and, especially in the past, there was quite a difference in the "cost" of operations depending on the platform.
For example, if the processor does not provide an arithmetic right shift instruction, the compiler would be mandated to emit a much slower DIV instruction of some kind, which could be a problem in an inner loop on slower processors. For these reasons, the C standard leaves it up to the implementor to do the most appropriate thing for the current platform.
In your case, your implementation probably chose arithmetic shift because you are running on an x86 processor, that uses 2's complement arithmetic and provides both bitwise and arithmetic shift as single CPU instructions.
Actually, languages like Java even have separated arithmetic and bitwise shift operators - this is mainly due to the fact that they do not have unsigned types to e.g. store bitfields.

Resources