tags:

views:

130

answers:

5

if i have int temp=(1<<31)>>31. How come the temp becomes -1? how do i get around this problem? thanks

+1  A: 

int is signed.

what 'problem' - what are you trying to do ?

int i = (1<<31); // i = -2147483648
i>>31;  // i = -1

unsigned int i = (1<<31); // i = 2147483648
i>>31;  // i = 1

ps ch is a nice command line 'c' intepreter for windows that lets you try this sort of stuff without compiling, it also gives you a unix command shell. See http://www.drdobbs.com/184402054

Martin Beckett
+5  A: 

In your case, the 1 in your expression is a signed type - so when you upshift it by 31, its sign changes. Then downshifting causes the sign bit to be duplicated, and you end up with a bit pattern of 0xffffffff.

You can fix it like this:

int temp = (1UL << 31) >> 31;

GCC warns about this kind of error if you have -Wall turned on.

Carl Norum
I checked the description of sign extension, but I can't see how it's related to the phenomenon observed by the OP. The problem is, that in his implementation the right shift is an arithmetic shift and int is signed and 32 bits long.http://en.wikipedia.org/wiki/Arithmetic_shift
Maciej Hehl
@Maciej, it looks like you're right - I'm misusing the term here. I'll edit to clearify that.
Carl Norum
+1  A: 

When you do (1<<31), the MSB which is the sign-bit is set(becomes 1). Then when you do the right shift, it is sign extended. Hence, you get -1. Solution: (1UL << 31) >> 31.

Rajorshi
Oops, already answered by Carl.
Rajorshi
+9  A: 

Ints are signed by default, which usually means that the high bit is reserved to indicate whether the integer is negative or not. Look up Two's complement for an explanation of how this works.

Here's the upshot:

[steven@sexy:~]% cat test.c
#include <stdint.h>
#include <stdio.h>

int main(int argc, char **argv[]) {
    uint32_t uint;
    int32_t sint;
    int64_t slong;
    uint = (((uint32_t)1)<<31) >> 31;
    sint = (1<<31) >> 31;
    slong = (1L << 31) >> 31;
    printf("signed 32 = %d, unsigned 32 = %u, signed 64 = %ld\n", sint, uint, slong);
}

[steven@sexy:~]% ./test
signed 32 = -1, unsigned 32 = 1, signed 64 = 1

Notice how you can avoid this problem either by using an "unsigned" int (allowing the use of all 32 bits), or by going to a larger type which you don't overflow.

Steven Schlansker
Beware also in particular that right shift of signed values is compiler dependent. So the output that is seen here is only so for a particular platform, other platforms might give other results.
Jens Gustedt
That's true, but that doesn't invalidate the fix of using unsigned or longer variables. I think.
Steven Schlansker
A: 

bit to indicate the sign is set when you do "such" left shift on a integer variable. Hence the result.

Praveen S