main()
{
int i=0xff;
printf("\n%d",i<<2);
}

please tell me how to work out this code...
and what will be the output...

4
Contributors
5
Replies
8
Views
8 Years
Discussion Span
Last Post by Banfa

If it's a binary number (don't let the hexadecimal value mislead you, i is still just a binary number, internally), and you moved the one's in that binary number, two columns to the left (filling up behind it with zero's).

What would you have?

We know that 0xff is 16 16's, or 16 * 16. So that's 1024, but now there's an adjustment needed, because the 4 part of 1024, has been over-written by zero's, from the << 2 bit shifting. So the 4 column of the binary number is now a zero.

Net effect is to remove the 4 from the answer, and 0xff << 2 becomes 1020 only.

A tutorial on it, should help. Google up one of the many tutorials on bit shifting, and go through it.

The hexadecimal number 0xff stands for its decimal equivalent f*16 + f = 15*16 + 15 = 255. Therefore, the decimal value of 0xff is 255!

The numerical operator << does left shift. Each left shift by one place (<< 1) is identical with multiplication by 2. Therefore, << 2 makes a left shift by two places which is identical with multiplication by 4 (2 times 2).

If we consider that the length of int usually is 32 bits or 8 bytes, the variable i contains 000000ff or in binary (msb) 0000 0000 0000 0000 0000 0000 1111 1111 (lsb). By left shifting this binary number by two places we get (msb) 0000 ... 0011 1111 1100 (lsb). What additionally happened during left shift is that on the msb side two bits were dropped off and on the lsb side 2 zero-bits were inserted.

Now the result is 0x3fc. Its decimal equivalent is (3*16+f)*16 + c = (3*16+15)*16+12 =1020, which could also be reproduced by stepwise decimal multiplication of 2 times 2: 255 times 2 is 510, 510 times 2 is 1020.

I hope that this small "tutorial" could clarify some misconceptions.

-- tesu

thanks a lot tesuu

To avoid further misconceptions, so what about right shift operator >> ? Consider this program:

int main(int argc, char *argv[])
{  int i;
i=0xff;       printf("%d    %d\n",i , i>>2); //  255    1020  (arithmetical right shift)
i=0xffffff01; printf("%d    %d\n",i , i>>2); // -255     -64  (arithmetical right shift)
return 1;
}

Binary representation of 0xff, 32 bit integers assuming, is (msb) 0000 0000 0000 0000 0000 0000 1111 1111 (lsb). Right-shifting this positive number by 2 places two things will happen:

firstly, 2 digits (11) are removed from lsb side
and
secondly, the original msb digit (0) is inserted twice on msb side, msb is short of "most significant bit".

The result is (msb) 0000 0000 0000 0000 0000 0000 0011 1111 (lsb) = 0x3f = dec 63. It's obviously that right-shift 1 place is equivalent to division by 2, and right-shifting 2 places means division by 4 such as 0xff>>2 = (dec 255/2 )/2=127/2=63.

There is an important fact to consider: In most programming languages the MSB codes the sign of integer numbers. So what will happen if we do a right shift on a negative integer number like the 2nd example in above program?

Binary representation of 0xffffff01 is (msb) 1111 1111 1111 1111 1111 1111 0000 0001 (lsb). Right-shifting this number 2 places will result in (msb) ??11 1111 1111 1111 1111 1111 1100 0000 (lsb) where 2 bits (01) were shifted out on lsb side but what to insert for (??) on msb side?

If we insert (00), the sign information would be destroyed. Therefore, in most programming languages the original msb bit will be inserted to preserve sign information. In our example original msb bit was (1) before shifting, therefore, (11) must be inserted and the final result after two-place right-shifting is (msb) 1111 1111 1111 1111 1111 1111 1100 0000 (lsb) = 0xffffffc0.

This kind of right shift preserving the sign is called arithmetic right shift contrary to logical right shift where only zeroes will be inserted which means that negative signs will be destroyed.

Btw, what is the absolute value of 0xffffffc0? Simply apply abs(0xffffffc0) or compute bitwise not then add +1: ~0xffffffc0 + 1, this is to compute two's complement, which all results in 0x40 = dec 64. Therefore 0xffffffc0 represents decimal -64 in our world.

-- tesu

Edited by tesuji: n/a

What you also need to be aware of is that right shift of a signed value in C is a platform defined operation and may be either arithmetic shift or logical shift.

That means the the operation

-2 >> 1

is not truely portable because the result could be either -1 or 127 depending on how the compiler has implemented right shift of a signed value.

In binary(decimal equivalent)

// arithmetic Shift
11111110(-2) >> 1 = 11111111(-1)
// logical shift
11111110(-2) >> 1 = 01111111(254)

Left shift of a signed value by more than the number of the bits in the value is undefined behaviour.

Generally it is considered best practice to avoid shifting signed values.

This topic has been dead for over six months. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.