个人总结操作符的特性,包括:按位操作符、位移操作符和单目操作符中的sizeof

来源:互联网 发布:手机联机软件 编辑:程序博客网 时间:2024/06/09 17:09

按位操作符

1. 按位与 |

个人理解,与数学中的交集 ∩ 相似

特性1.遇1不变,遇0为0
两个bit位a,b
a=1,b=1 a&b=1;
a=1,b=0 a&b=0;
a=0,b=0 a&b=0;
举例说明:
10的二进制为:00001010;
5的二进制为:00000101;
10&5:
00001010
00000101
—————
00000000
10&5=0;
特性2.交换律
例如:(2&3)&4=2&(3&4)
验证:
2:0010;
3:0011;
4:0100;
2&3=0010;(2&3)&4=0000;
3&4=0000;2&(3&4)=0000;

没有结合律
例如:5&3+5&2和5&(3+2)是不相等的,前者等于5,后者等于0,可自行验证;

特性3.
a&a=a;
a&0=0;
a&(-1)=a;(因为-1的补码是全1,则结果不变(特性1))
奇数&1=1;偶数&1=0;
(因为奇数的第一位二进制位是1,偶数的第一位二进制位是0)

特性4.一个数持续与它本身减一做按位与运算,最终会得到0;
例如:

int main(){int n=23;while(n){     n=n&(n-1);}//最终,循环会跳出,即n=0;return 0;}

并且,循环次数与二进制中1的个数相同。

例如:

int main(){int n=10;//二进制为:0000 1010int count=0;while(n){     n=n&(n-1);     count++;}//最终,循环会跳出,count=2;return 0;}

2. 按位或 |

个人理解,与数学中的并集∪相似

特性1.遇0不变,遇1为1
两个bit位a,b
a=1,b=1 a|b=1;
a=1,b=0 a|b=1;
a=0,b=0 a|b=0;
举例说明:
10的二进制为:00001010;
5的二进制为:00000101;
10|5:
00001010
00000101
—————
00001111
10|5=31;
特性2.交换律
例如:(2|3)|4=2|(3|4)
验证:
2:0010;
3:0011;
4:0100;
2|3=0011;(2|3)|4=0111;
3|4=0111;2|(3|4)=0111;

没有结合律
例如:5|3+5|2和5|(3+2)是不相等的,前者等于15,后者等于5,可自行验证;

特性3.
a|a=a;
a|0=a;
a|(-1)=-1;(因为-1的补码是全1,则结果变1(特性1))
奇数&1=奇数;偶数&1=偶数+1;
(因为奇数的第一位二进制位是1,偶数的第一位二进制位是0)

3. 按位异或 ^

特性1.同0异1(相同为0,不同为1)
两个bit位a,b
a=1,b=1 a^b=0;
a=1,b=0 a^b=1;
a=0,b=0 a^b=0;
举例说明:
10的二进制为:00001010;
5的二进制为:00000101;
10^5:
00001010
00000101
—————
00001111
10^5=15;
特性2.交换律
例如:(2^3)^4=2^(3^4)
验证:
2:0010;
3:0011;
4:0100;
2^3=0001;(2^3)^4=0101;
3^4=0111;2^(3^4)=0101;

没有结合律
例如:5^3+5^2和5^(3+2)是不相等的,前者等于15,后者等于0,可自行验证;

特性3.
a^a=0;
a^0=a;

位移操作符

1. 左移

左移操作符:<<
将二进制位向左移位,左边丢弃,右边补0
例如:
25的二进制是:
00000000 00000000 00000000 00011001
25<<1:
00000000 00000000 00000000 00110010
25<<8:
00000000 00000000 00011001 00000000

2. 右移
右移操作符:>>
(根据编译器不同,分成算术右移和逻辑右移,一般都是算术右移)
(1)算术右移
将二进制位向右移位,右边丢弃,左边补符号位
例如:
-25的二进制是:
10000000 00000000 00000000 00011001
-25<<1:
11000000 00000000 00000000 00001100
-25>>8
11111111 10000000 00000000 00000000

(2)逻辑右移
将二进制位向右移位,右边丢弃,左边补0
例如:
-25的二进制是:
10000000 00000000 00000000 00011001
-25<<1:
01000000 00000000 00000000 00001100
-25>>8
00000000 10000000 00000000 00000000

移位操作符的运算:
例如:

int n=25;n=n>>1;//或者写成n>>=1;不能写成int n=25;n>>1;

否则编译警告:warning C4552: “>>”: 运算符不起任何作用;应输入带副作用的运算符
“>>和<<”只是个运算符,和+、-等运算符一样,只执行运算的功能,却不会改变操作数的值,因此作为左操作数的a在执行移位操作后会保持原来的值不变
(3)无符号整数除2的n(n>0)次幂相当于右移n位
用于有除法运算的时候替换除法,除法是最慢的运算;
例如:
4/2替换成4>>1
64/8替换成64>>3

单目操作符:sizeof

单目操作符里有一个操作符比较重要:sizeof
以下几点需注意:
**1.**sizeof:返回操作数的类型长度,以字节为单位;

在此回顾一个知识点,各数据类型的大小:
char :1字节; short :2字节; int :4字节;
long :4或8字节; long long :8字节; float :4字节;
double :8字节

简单几个例子:
sizeof(int)=4; int a sizeof(a)=4;
sizeof(char)=1; char a sizeof(a)=1;
sizeof(double)=8; double a sizeof(a)=8;
从以上几个例子可以看出sizeof返回的是操作数的类型长度

再补充一些内容:sizeof对地址的操作
例1:

  int main(){            int* p;            int num=sizeof(p);            return num;}

结果返回为4;
因为指针存放的是地址,在32位系统下,地址为32位二进制数,即32个bit位,
1个字节为8个bit,所以地址的大小为4字节;
例2:

         int main(){            int arr[5]={1,2,3,4,5};            int num=sizeof(arr);            return num;}

结果返回为20;
因为arr在sizeof(arr)中代表整个数组的地址,定义该数组时在内存中分配了
5个int类型元素的空间,即5个4字节大小的空间。
例3:

  int main(){            int arr[5]={1,2,3,4,5};            int num=sizeof(arr[0]);            return num;}

结果返回为4;
因为arr[0]代表数组中的第一个元素,即1,所以sizeof(arr[0])==sizeof(1)==sizeof(int)==4;

**2.**sizeof执行操作时发生在编译阶段,所以不会访问内存
由此引申两个例题:
(1)以下代码是否有错?如果没错,返回值是多少

          int main(){            int arr[5]={1,2,3,4,5};            int num=sizeof(arr[5]);            return num;}

答案:返回值为4;
解析:很多人刚开始接触sizeof的时候,会认为arr[5]不存在,认为这段代码是错误的。实际上,sizeof是操作符,并非函数;sizeof执行操作时发生在编译阶段,而非运行阶段。虽然arr[5]并不存在,但这里也并没有真正地访问arr[5],而是仅仅根据数组元素的类型来确定其值。
(2)求下面代码的打印结果:

   int main(){        int a=10;        int b=20;        printf("%d\n",sizeof(a=b+1));        printf("%d\n",a);        return 0;}

答案:4和10
解析:“细心”的同学可能会回答4和21,因为a=b+1这部分代码。
实际上,sizeof执行操作时发生在编译阶段,而非运行阶段;
所以并没有真正进行运算。

**3.**sizeof不是函数
很多同学看见sizeof后面跟着(),就误认为它是函数,实际上不是。
可用以下方法自行证明:

  int main(){        int a=10;        printf("%d\n",sizeof(a));//打印4        printf("%d\n",sizeof a);//打印4        printf("%d\n",sizeof (int));//打印4        printf("%d\n",sizeof int);//错误        return 0;}

上面的结果可以告诉我们,sizeof并非函数。

原创粉丝点击