C语言中的位操作符有以下六种:
& 按位与
| 按位或
^ 按位异或
~ 取反
<< 左移
>> 右移
1. & 按位与
规则:1 & 1 = 1; 1 & 0 = 0; 0 & 1 = 0; 0 & 0 = 0;
即 & 按位与操作符是双目操作符,它的作用是运算符两边均为1则结果为1,其他情况则为0。
示例:13 & 8 即00001101 &00001000 = 00001000 所以13 & 8 = 8。
另,负数按补码形式参加按位或运算。
实战应用:
(1)清零。n & (n-1)
一个数减一,在二进制看来,是他的最低位的’1‘变成了’0‘,这个’1‘后面的’0‘全部变成了’1‘,那再与他本身进行按位与运算,就把这个数的最低位’1‘变成了’0‘。(《剑指offer》p100)
(2)取一个数的指定位
例:设X=10101110,我要单独拿出它的低四位'1110',那么我就可以
用 X & 0000 1111 = 0000 1110 即可得到;还可用来取X的2、4、6位。
2。 | 按位或
规则:0|0=0; 0|1=1; 1|0=1; 1|1=1;
即 :参加运算的两个对象只要有一个为1,其值为1。
例如:3|5 即 0000 0011 | 0000 0101 = 0000 0111 因此,3|5的值得7。
另,负数按补码形式参加按位或运算。
实战应用
(1)把一个数的某些位置1。
例:将X=10100000的低4位置1 ,用 X | 0000 1111 = 1010 1111即可得到。
3. ^ 取反
规则:0^1 = 1; 1^0 = 1; 0^0 = 0; 1^1 = 1; (即不同为1,相同为0)
例如: 8^6 即 1000^0110 = 1110 因此,8^6 = 14
实战应用:
(1)交换两数的值
a=5,b=4。
a = a^b;
b = a^b;
a = a^b;
4.左移运算符(<<)
将一个运算对象的各二进制位全部左移若干位(高位丢弃,低位补0)。
例:a = a << 2 将a的二进制位左移2位,右补0,
左移1位后a = a * 2;
若左移时舍弃的高位不包含1(正数),则每左移一位,相当于该数乘以2。
5.右移运算符(>>)
将一个数的各二进制位全部右移若干位,正数右移时高位补0,负数右移时高位是补0还是补1取决于编译系统的规定。Turbo和很多操作系统规定补1;
操作数右移n位(n>0),相当于该数除以2的n次方。(此方法可以代替除法运算,提高效率)
例如:a = a >> 2 将a的二进制位右移2位,
6.sizeof
1.功能:返回一个变量或者类型的大小(以字节为单位);在 C 语言中,sizeof() 是一个判断数据类型或者表达式长度的运算符。
(1)sizeof是操作符而不是函数
short s = 20;
int a = 10;
printf("%d",sizeof(s=a+1));//输出2
printf("%d",s); //输出20
sizeof里面的表达式不进行运算,因为sizeof是在编译阶段发生作用的,但s=a+1要等运行阶段才发生。
(2)sizeof与数组之间的爱恨情仇
只有以下两种情况数组名代表整个数组:
①数组名单独在sizeof内时。② &数组名(如&a)
int a[ ] = {1,2,3,4};
sizeof(a) =16 数组名单独在sizeof内,表示整个数组,一个int型元素4个字节,4*4=16。
sizeof(a+0) =4 此处数组名不是单独在sizeof内,那表示的就是首元素地址,+0,还是首元素地址,存地址的指针变量大小是四节。
sizeof(*a) =4 *a代表首元素地址,地址嘛,你懂的。
sizeof(a+1) =4 首元素地址加1,那就是第二个元素的地址,还是地址。
sizeof(a[1]) =4 a[1]数组中的第一个元素,整型数据4字节。
sizeof(&a) =4 此处&a就代表整个数组的地址,但是 地址啊,放指针变量里面的,所以还是4字节。
sizeof(*&a) = 16 &a是a的地址,那*&a就代表整个数组了,所以是16字节。
sizeof(&a+1) =4 此处&a代表的可不是整个数组了,因为人家后面带了个’+1‘呢,所以这是首元素地址加1,第二个元素的地址。
sizeof(&a[0]) =4 这就不用说了,取第一个元素地址
sizeof(&a[0]+1) = 4 嗯,第二个元素地址。