Implementation of logical right shift of negative numbers in c

℡╲_俬逩灬. 提交于 2019-12-11 04:15:52

问题


Is there a simple way to do logical right shift in c for negative numbers like how we have >> for arithmetic right shift?


回答1:


Right-shifting negative numbers invoke implementation-defined behavior in C. What will happen is not specified by the standard, but left to the compiler to specify. So it can either result in an arithmetic shift, or a logical shift, or perhaps something else entirely (like rotation, though I've never heard of that). You can't know or assume which method that applies on your compiler, unless you read the specific compiler documentation.

Unsigned numbers always use logical shift however. So if you want logical shift on a negative number, portably, then convert to unsigned before the shift:

int32_t i = -1;

i = (int32_t) ((uint32_t)i >> n); // guaranteed to give logical shift

Similarly, if you want to guarantee an arithmetic shift:

int32_t i = -1;
bool negative = i < 0;

if(negative)
{
  i = -i;
}

i = (int32_t) ((uint32_t)i >> n);

if(negative)
{
  i = -i;
}



回答2:


Logical right shifting is done by casting the int value to unsigned before shifting:

int lsr(int n, int shift) {
    return (int)((unsigned)n >> shift);
}

Arithmetic right shifting cannot be dpne diretly with the >> operator on negative values in C as its effects are implementation defined. Here is a simple alternative without tests that replicates the sign bit for all values on 2s complement architectures:

int asr(int n, int shift) {
    unsigned u = (unsigned)n;
    return (int)((u >> shift) | ~(((u & (unsigned)INT_MIN) >> shift) - 1));
}

And here is a simple test program:

#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

int lsr(int n, int shift) {
    return (int)((unsigned)n >> shift);
}

int asr(int n, int shift) {
    unsigned u = (unsigned)n;
    return (int)((u >> shift) | ~(((u & (unsigned)INT_MIN) >> shift) - 1));
}

int main(int argc, char *argv[]) {
    int n = (argc < 2) ? -2 : strtol(argv[1], NULL, 0);
    int shift = (argc < 3) ? 2 : strtol(argv[2], NULL, 0);

    printf("%d >> %d = %d\n", n, shift, asr(n, shift));
    printf("%d >>> %d = %d\n", n, shift, lsr(n, shift));

    return 0;
}


来源:https://stackoverflow.com/questions/39853049/implementation-of-logical-right-shift-of-negative-numbers-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!