位操作符
& |^ ~ << >>
只能用于整数,其中<<和>>操作符是双目操作符,它们的右操作数必须为非负整数;
左移运算,空位都用0填充;
右移运算,unsigned类型空位用填充,signed类型空位有的用0填充,有的用符号位填充,取决于具体实现;
功能 示例 位运算
去掉最后一位 (101101->10110)
x >> 1
在最后加一个0
(101101->1011010) x << 1
在最后加一个1
(101101->1011011) x << 1+1
把最后一位变成1
(101100->101101) x | 1
把最后一位变成0
(101101->101100) x | 1-1
最后一位取反 (101101->101100)
x ^ 1
把右数第k位变成1
(101001->101101,k=3) x | (1 << (k-1))
把右数第k位变成0
(101101->101001,k=3) x
& ~ (1<< (k-1))
右数第k位取反
(101001->101101,k=3) x ^ (1 << (k-1))
取右数第k位
(1101101->1,k=4) x >> (k-1) & 1
取末三位 (1101101->101)
x & 7
取末k位
(1101101->1101,k=5) x & (1 << k-1)
把末k位变成1
(101001->101111,k=4) x | (1 << k-1)
末k位取反
(101001->100110,k=4) x ^ (1 << k-1)
把右边连续的1变成0
(100101111->100100000) x & (x+1)
把右起第一个0变成1
(100101111->100111111) x | (x+1)
把右边连续的0变成1
(11011000->11011111) x | (x-1)
取右边连续的1
(100101111->1111) (x ^ (x+1)) >> 1
去掉右起第一个1的左边 (100101000->1000)
x & (x | (x-1))
取全1:~0
末尾取1:1 << k-1
强制赋值1:|
强制赋值0:&
使用移位运算符时, 如果被移位的对象的长度为n,那么移位计数必须大于或者等于0,而且要严格小于n;
考虑一个比较流行的不使用临时变量交换两个数的函数语句
(*a) ^= (*b) ^= (*a) ^= (*b);
整个语句位于两个序列点之间,并且两次修改了同一变量,所以这个语句是不可移植的,标准视其为未定义的。
可以使用替代的写法:
(*a) ^= (*b);
(*b) ^= (*a);
(*a) ^= (*b);
实际是是利用了^运算的逆运算是它自身的这个特点
(*a) = (*a) # (*b);
(*b) = (*a) @ (*b);
(*a) = (*a) @ (*b);
(通法:其中#和@互为逆运算)
例如:
(*a) += (*b);
(*b) = (*a) -(*b);
(*a) -= (*b);
1#include 2 3intmain(void) 4{ 5 printf("%d\n\n", 6 7 printf("%d\n", 8 printf("%d\n", 9 printf("%u\n", 10 printf("%d\n", 11 printf("%u\n", 12 printf("%d\n\n\n", 13 14 printf("%d\n", 15 printf("%d\n", 16 printf("%u\n", 17 printf("%d\n", 18 printf("%u\n", 19 printf("%d\n", 20 21 22 23 /* 24 25 26 27 28 29 return0; 30} |