Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Signed right shift: which compiler use logical shift

I tested right shift with Visual Studio, Ubuntu's GCC, Intel compiler, MinGW. All shift in the sign bit. I guess Xcode's GCC does the same.

I know that the behavior is implementation specific, but it looks like that all major desktop/server compilers implement arithmetic shift. Are there any widely used compiler that doesn't shift in the sign bit?

Thank you.

like image 504
pic11 Avatar asked Jun 27 '11 01:06

pic11


2 Answers

C runs on a lot of different architectures. I mean a lot of different architectures. You can get C code running on an embedded DSP and on a Cray supercomputer.

Most of the "implementation-defined" parts of the C standard that people take for granted really only do break on obscure architectures. For example, there are DSPs and Cray supercomputers where CHAR_BIT is something huge like 32 or 64. So if you try out your code on an x86, and maybe if you're generous a PowerPC, ARM, or SPARC, you're not likely to run into any of the really weird cases. And that's okay. Most code these days will always run on a byte-oriented architecture with twos-complement integers and arithmetic shifts. I have no doubt that any new CPU architectures in the foreseeable future will be the same.

But let's look at the two most common representations for integers: twos-complement and ones complement:

switch ((-1) >> 1) {
case 0:
case -0:
    puts("Hello, one's complement world!");
    // Possibly sign-magnitude.
    break;
case -1:
    puts("Hello, two's complement world!");
    break;
default:
    puts("Hello, computer without arithmetic shift");
    break;
}

Don't sweat it. Just stick to / when you want to divide, and >> when you need to shift. Even bad compilers are good at optimizing these operations. (And remember that x/2 != x>>1 if x is negative, unless you're on a one's complement machine, which is almost certainly not true.)

The standard does guarantee that if (int) x is not negative, then (int) x >> n == (unsigned) x >> n, so there is not a lot of room for a compiler to do something completely unexpected.

like image 128
Dietrich Epp Avatar answered Sep 19 '22 07:09

Dietrich Epp


Generally it depends more on the target architecture that the compiler used. If the arch has both arithmetic (signed) and logical (unsigned) shift instructions, then C compilers for that arch will use whichever is appropriate. On the other hand, if it has only logical shifts, the C compiler will just use that, even though it doesn't 'do the right thing' for negative values, as the C spec allows the compiler to do anything.

like image 30
Chris Dodd Avatar answered Sep 20 '22 07:09

Chris Dodd