C中的移位运算符(<<,>>)是算术还是逻辑?

在 C 中,移位运算符 (<<, >>) 是算术还是逻辑?

请先 登录 后评论

3 个回答

Greg Hewgill

左移时,算术和逻辑移位没有区别。右移时,移位的类型取决于被移位的值的类型。

(作为那些不熟悉差异的读者的背景,“逻辑”右移 1 位会将所有位向右移并用 0 填充最左边的位。“算术”移位将原始值保留在最左边的位。在处理负数时,差异变得很重要。)

在移位无符号值时,C 中的 >> 运算符是逻辑移位。移位有符号值时,>> 运算符是算术移位。

例如,假设是 32 位机器:

signed int x1 = 5;
assert((x1 >> 1) == 2);
signed int x2 = -5;
assert((x2 >> 1) == -3);
unsigned int x3 = (unsigned int)-5;
assert((x3 >> 1) == 0x7FFFFFFD);
请先 登录 后评论
John Scipione

以下是保证 C 中 int 的逻辑右移和算术右移的函数:

int logicalRightShift(int x, int n) {
    return (unsigned)x >> n;
}
int arithmeticRightShift(int x, int n) {
    if (x < 0 && n > 0)
        return x >> n | ~(~0U >> n);
    else
        return x >> n;
}
请先 登录 后评论
Nick

就您获得的转变类型而言,重要的是您要转变的值的类型。一个典型的错误来源是当您将文字转换为例如屏蔽位时。例如,如果你想去掉一个无符号整数的最左边的位,那么你可以试试这个作为你的掩码:

~0 >> 1

不幸的是,这会给您带来麻烦,因为掩码将设置其所有位,因为被移位的值 (~0) 是有符号的,因此执行算术移位。相反,您希望通过将值显式声明为无符号来强制进行逻辑转换,即通过执行以下操作:

~0U >> 1;
请先 登录 后评论