Question

In the following code,

#include <stdio.h>
#include<conio.h>
main()
{
    int y=-01;
    y<<=3;
    printf("%d\n",y);
    y>>=3;
    printf("%d",y);
    getch();
}

I read in a book that while using the right shift operator on y, the signed bit may or may not be preserved depending on my compiler. Why is that? What is the concept behind this? Please elaborate.

Was it helpful?

Solution

Some processors have only an "unsigned" right shift (fills the sign bit with 0's) or a signed right shift (fills the size bit with copies of the current sign bit). Since some processors only have one or the other, but not both, the standard doesn't try to mandate one behavior or the other.

For what it's worth, many (most?) current processors have instructions to do both. For example, the x86 includes both shr (logical shift right -- fills with 0's) and sar (arithmetic shift right -- fills with copies of the sign bit).

OTHER TIPS

The following quotes from the C11 standard (6.5.7 Bitwise shift operators)might be helpful :

  • The result of E1 << E2 is E1 left-shifted E2 bit positions; vacated bits are filled with zeros. If E1 has an unsigned type, the value of the result is E1 × 2^E2, reduced modulo one more than the maximum value representable in the result type. If E1 has a signed type and nonnegative value, and E1 × 2^E2 is representable in the result type, then that is the resulting value; otherwise, the behavior is undefined.
  • 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 / 2^E2. If E1 has a signed type and a negative value, the resulting value is implementation-defined.

This is true. Because, there are four types of shifting available.

  1. Arithmetic Shift

  2. Logical Shift

  3. Rotate No carry Shift

  4. Rotate Through Carry Shift

In first two types, the position of sign-bit is preserved while shifting shifting to the right or left. Generally in the C or any derivation of C uses the Arithmetic Shift & Logical Shift. In C, the Right Shift is Arithmetic Shift & Left Shift is Logical. But in Java, both shifting are Logical Shifting.

In the last two types, the positioned of the Sign Bit are not maintained. The bits are shifted in regular manner. The Rotate No Carry falls under the Circular Shift which is mostly used in cryptography to retain all the bits.

The C Programming, although implements the Logical & arithmetic Shift, but it also has the capability to recognize the Circular Shifting in the following way:

unsigned int x;
unsigned int y;
/* This Code is Just for reference from Wikipedia */    
y = (x << shift) | (x >> (sizeof(x)*CHAR_BIT - shift));

I this information is not Sufficient, then you can go through the Wikipedia main article which is linked from the title of all the shifts above.

lets see this example

consider this value 1111 1111 1111 1111

if your compiler is 16 bit you did right shift

value will become 1111 1111 1111 1110

if your compiler is 32 bit and you did right shift

value will become 0000 0000 0000 0001 1111 1111 1111 1110

you did the right shift of same value but you will get different result depending up on your compiler.

use %x to print the hexa decimal notation of decimal value.

see this code :

#include <stdio.h>
main()
{
   int y=-01;
    printf("%d\n",y);
    printf("%x\n",y);

    y<<=3;
    printf("%d\n",y);
    printf("%x\n",y);
    y>>=3;
    printf("%d\n",y);
    printf("%x\n",y);


    y=127;
    printf("%d\n",y);
    printf("%x\n",y);

    y<<=3;
    printf("%d\n",y);
    printf("%x\n",y);
    y>>=3;
    printf("%d\n",y);
    printf("%x\n",y);


    y=32767;
    printf("%d\n",y);
    printf("%x\n",y);

    y<<=3;
    printf("%d\n",y);
    printf("%x\n",y);
    y>>=3;
    printf("%d\n",y);
    printf("%x\n",y);


    getchar();
}

OUTPUT ON 64-bit machine :

-1 ffffffff -8 fffffff8 -1 ffffffff 127 7f 1016 3f8 127 7f 32767 7fff 262136 3fff8 32767 7fff

OUTPUT ON 32-bit machine :

-1 ffffffff -8 fffffff8 -1 ffffffff 127 7f 1016 3f8 127 7f 32767 7fff -8 fffffff8 -1 ffffffff

when reaches to maximum value of 32 bit signed integers , you will find the compiler dependency on shifting.

here 8-bit signed integers explained with 1's and 2's compliment representation
Signed number representations

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top