& |^ ~ << >>
只能用于整数,其中<<和>>操作符是双目操作符,它们的右操作数必须为非负整数;
左移运算,空位都用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 <stdio.h> 2 3intmain(void) 4{ 5 printf("%d\n\n", ~3+1); /*取反加1得到相反数*/ 6 7 printf("%d\n", ~0); 8 printf("%d\n", (unsigned int) ~0); 9 printf("%u\n", (unsigned int) ~0); 10 printf("%d\n", ( (unsigned int) ~0) >>1); 11 printf("%u\n", ( (unsigned int) ~0) >>1); 12 printf("%d\n\n\n", (int) ( ( (unsigned int) ~0) >>1) ); 13 14 printf("%d\n", ~0); 15 printf("%d\n", (unsigned char) ~0); 16 printf("%u\n", (unsigned char) ~0); 17 printf("%d\n", ( (unsigned char) ~0) >>1); 18 printf("%u\n", ( (unsigned char) ~0) >>1); 19 printf("%d\n", (char) ( ( (unsigned char) ~0) >>1) ); 20 21 22 23 /* 24 * * * %d格式取32位输出,最高位为符号位,当右移一位时,去除了符号位,输出时显示为正整数(31位) 25 * * * %u格式也是取32位输出,没有符号位,右移一位后,输出时显示31位正整数 26 * * *当强制转换为unsigned int时,取32位,并将最高位的符号性质抹去 27 * * *当强制转换为unsigned char时,取8位,无所谓符号位(以%d或者%u打印时,最高位在32位) 28 */ 29 return0; 30}
|