目录
1:位操作符
位操作操作的都是二进制位,且操作数必须是整数。同时不论整数是否带符号(既是否是正数或者负数),都是以该变量->补码 参与运算。
1:& 按位与
计算规则:对应的二进制位参与运算,只要有0就是0,两个同时为1才是1。
int a=15;
int b=-2;
int c=a&b;
printf("%d",c);
首先 a=15, 是正数,所以在二进制表示中,其原码、反码、补码是一样。
15 补码: 00000000 00000000 00000000 00001111
b=-2;是负数,首先要先得到-2 原码,然后原码->反码,最后反码->补码
负数only:
原码--->反码:符号位不变,其余所以数值为全部反转
反码--->补码:最后一位加1
补码--->原码:符号位不变,其余数值位反转,最后+1
-2 原码:10000000 00000000 00000000 00000010
-2 反码:111111111 11111111 11111111 11111101
-2 补码:111111111 11111111 11111111 11111110
注意: a & b 的结果并不会改变 a 跟 b ,只是将 a& b的结果 给了 c,但是并不会影响 a 跟 b 自身的数值。
所以衍变如下:
a:00000000 00000000 00000000 00001111
&
b:111111111 11111111 11111111 11111110
根据原则,两个同时为1才为1,有一个为0 就是 0
c:00000000 00000000 00000000 00001110.
这个结果最高位是0,所以是正数,然后根据最后1110,得到最终结果是14。
2:| 按位或
运算规则:只要有1就是1,两个同时为0才是0
a:00000000 00000000 00000000 00001111
|
b:111111111 11111111 11111111 11111110
根据原则:只要有1就是1,两个同时为0才是0
c:11111111 11111111 11111111 11111111
然后分析c的二进制,首先我们通过位操作得到的结果是补码,然后发现最高位是1,所以这是负数,这个时候要将这个补码转为原码:
补码----> 原码: 符号位不变,其余所有数值为取反,最后结果再+1.
c:11111111 11111111 11111111 11111111 ----> (除符号位其余取反) 10000000 00000000 00000000 00000000 ---> (末位加1) 10000000 0000000 00000000 00000001,所以得到最终结果是c =-1
3:^ 按位异或
运算规则: 相同为0(可以同时是0,也可以同时是1,不论那种情况,在异或位操作符下,都是0),相异为1
a:00000000 00000000 00000000 00001111
^
b:11111111 11111111 11111111 11111110
c:11111111 11111111 11111111 11110001
然后分析c的二进制,首先我们通过位操作得到的结果是补码,然后发现最高位是1,所以这是负数,这个时候要将这个补码转为原码:
补码----> 原码: 符号位不变,其余所有数值为取反,最后结果再+1.
11111111 11111111 11111111 11110001 ----> 100000000 00000000 00000000 00001110 ---> 100000000 00000000 00000000 00001111
所以最后得到的结果是 -15
异或操作符特点:
a^a=0;//a的每一位都是相同的,所以相同为0,a^a的结果是每一个比特位都成为0
a^0=a;
4:~按位取反
int a=15;
int b=~a;
a:00000000 00000000 00000000 00001111
~
b: 11111111 11111111 11111111 11110000
然后分析b的二进制,首先我们通过位操作得到的结果是补码,然后发现最高位是1,所以这是负数,这个时候要将这个补码转为原码:
补码----> 原码: 符号位不变,其余所有数值为取反,最后结果再+1.
11111111 11111111 11111111 11110000 ---> 10000000 00000000 00000000 00001111 ----> 10000000 00000000 00000000 00010000 ,所以最后得到结果是 -16
2:逗号操作符
逗号表达式,就是用逗号隔开多个表达式,执行顺序是从左到右依次执行,但是整个表达式的结果是最后一个表达式的结果。
int main()
{
int a = 110;
int b = 5;
int c = (a, a=a-b,b=b*2, a-b);//a=105,b=10
printf("%d\n", c);
return 0;
}
因为从左到右依次执行,所以每次执行后的结果都会影响最后一个表达式,见如下:
首先先算 a=a-b ----> a=105;
b=b*2 -------> b=10;
a-b --------> 95
3:表达式求值
3.1 整型提升
c语言中整型算术运算总是默认以整型类型的精度来进行计算的,所以对于char 以及 short这种字节空间 小于 4个字节的数据类型,会默认将其转换为4个字节的int 类型 ,再进行计算。
3.2算术转换
如果某个操作符的左右两边操作数属于不同的数据类型,那么除非其中一个操作数转换为另外一个操作数类型,否则操作就无法进行:
1 long double
2 double
3 float
4 unsigned long int
5 long int
6 unsigned int
7 int
如果某个操作数的类型在上图中排名靠后,那么首先要将该操作数转换成另一个操作数类型后再进行计算。