返回首页   进站必读

6.2 按位左移右移


6.2 按位左移右移

6.2.1 整数左移

在一定的取值范围内,将一个整数左移1位相当于乘以2;右移一位相当于对2取整。例如:

100 = 0110 0100b
100 >> 1 = 0011 0010b
0011 0010b = 50
100 << 1 = 1100 1000b
1100 1000b = 200

6.2.2 无符号数移位规则

操作数为无符号数时,右移时高位补0,左移时低位补0;

6.2.3 有符号数移位规则

如果是正数,那么高位移入0;
如果是负数,那么高位移入1还是0不一定,这是Implementation-defined的,对于x86平台的gcc编译器,最高位移入1, 也就是仍保持负数的符号位,这种处理方式对负数仍然保持了“右移1位相当于除以2”的性质。
示例:

// 将一个数循环左移

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

typedef unsigned int u32_t;

#if 0
u32_t left_shift(u32_t a, int n)
{
	n %= 32;
	int i;

	for(i = 0; i < n; ++i)
		a = (a << 1)| (a >> 31);

	return a;
}
#else

u32_t left_shift(u32_t a, int n)
{
	n %= 32;
	a = (a << n) | (a >> (32-n));

	return a;
}
#endif

int main(int argc, char *argv[])
{
	int a = 0x12345678;
	int n = atoi(argv[1]);

	printf("0x%x\n", left_shift(a, n));

	return 0;
}

6.2.4 常见用法

1、设置位

a |= 1<<i;		// 设置 a 的第 i 位为 1

2、清除位

a &= ~(1<<i);		// 设置 a 的第 i 位为 0

3、测试位

if (a & (1<<i))		// 设置 a 的第 i 位是否为 1
if (!(a & (1<<i)))	// 设置 a 的第 i 位是否为 0
if (((a >> i) & 0xF) == 0x9)	// 设置 a 的第 i 位至 第 i+4 位是否为 1001b

4、获取位

(a>>i) & 0x1		// 获取 a 的第 i 位
(a>>i) & 0xF		// 获取 a 的第 i 位 至 第 i+4 位