Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

bitwise shifiting question

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

like image 979
w31 Avatar asked Dec 05 '22 02:12

w31


2 Answers

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.

like image 149
Steven Schlansker Avatar answered Dec 27 '22 07:12

Steven Schlansker


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.

like image 20
Carl Norum Avatar answered Dec 27 '22 06:12

Carl Norum