问题
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