目录
1.操作符的分类
- 算数操作符:+,-,*,/,%
- 移位操作符:<< , >>
- 位操作符:&,|,^,~
- 赋值操作符:=,+=,-=,*=,/=,%=,<<=, >>= ,&= ,|=,^=
- 单目操作符:!,++,- -, *,+,-,~,sizeof,&(取地址)
- 关系操作符:< ,>,>= , <= ,== ,!=
- 逻辑操作符:&&,||
- 条件操作符:?,:
- 逗号表达式:,
- 下标引用操作符:[ ]
- 函数调用:()
- 结构成员访问:. ,->
2.二进制和进制转换
与十进制一样,二进制,八进制,十六进制都是对数的不同表示形式,其本质是指的同一个数字。
15的二进制:1111
15的十进制:15
15的八进制:17
15的十六进制:F
二进制和十进制的规则差不多:
- 二进制满2进1
- 二进制的每一位数字都是0和1组成
2.1 二进制转化为十进制
其实十进制和二进制都是每一位上的数字乘以权重再相加形成的
比如:
而二进制的权重就是2^0 , 2^1 , 2^2……
2.2 十进制转化为二进制
转化方法就是用十进制数依次除以2得到余数,一直除到0,从下往上得到的余数就是二进制数
所以125的二进制数为:1111101
2.3 二进制转化为八进制和十六进制
2.3.1 二进制转化为八进制
八进制中的每个数字都是由0~7组成的,所以至多需要3个二进制位就可以存放一个八进制的一位数(因为7 的二进制数位111),所以直接从右向左依次取3个二进制位转化为一个十进制数字就可以形成八进制数,如果到左边位数不够直接换算就行。
比如:
2.3.2 二进制转化为十六进制
十六进制的每个数字都是由0~ 9和a~ f组成的,其中a~ f表示的数是:a 10,b 11 ,c 12, d 13, e 14, f 15 。所以至多需要4个二进制位就可以存放一个十六进制的一位数(因为f的二进制是:1111),所以直接依次从右向左取4个二进制位转化为10进制数字就可以表示十六进制数字了,其中不够的直接换算就行了。
3.原码,反码,补码
整数的2进制表示方法有3种,即原码,反码,补码
有符号整数(signed)的三种表示方法种包含符号位和数值位两部分,其中最高的一位是符号位,其余的都是数值位
符号位用0表示正,1表示负
正整数的原码,反码,补码都相同
负整数的三种表示方法都不同
原码:直接将数值按照正负数的形式翻译成二进制得到的就是原码
反码:符号位不变,将数值位按位取反得到反码
补码:反码加1得到补码
补码得到原码的方法:取反,加1
对于整型来说:数据存放在内存中其实存放的是补码
那为什么计算机中存储的是补码呢,原因在于:使用补码,可以将符号位和数值域相统一,同时,加法和减法可以统一处理(cpu只有加法器),补码和原码相互转换,其运算过程相同,不需要额外电路。
比如计算1-1只能转换为1+(-1)才能计算
因为整型int的字节数是4,所以bit位位32(一个字节8位)
1 的补码就是原码:00000000 00000000 00000000 00000001
-1的原码:10000000 00000000 00000000 00000001
-1的反码:111111111 111111111 111111111 111111110
-1的补码:111111111 111111111 111111111 111111111
使用原码计算相加得到:10000000 00000000 00000000 00000010
值为-2,所以使用原码计算减法错误
使用补码计算相加得到:1 00000000 00000000 00000000 00000000
第一位1溢出,即为00000000 00000000 00000000 00000000,由于符号位为0是正数,不要转换为原码,则结果就是0.
4.移位操作符
<< 左移操作符 , >>右移操作符
移位操作符只能操作整数
4.1 左移操作符
移位规则:左边丢弃,右边补0
int main() {
int num = 10;
int n = num << 1;
printf("%d\n", num);
printf("%d\n", n);
return 0;
}
当一个数执行移位操作时,本身值不变,只是表达式的值改变。
4.2 右移操作符
移位规则:
1.逻辑右移:左边用0补充,右边丢弃
2.算数右移:左边用符号位填充,右边丢弃
这两种方法是由编译器选择的
int main() {
int num = 10;
int n = num >> 1;
printf("%d\n", num);
printf("%d\n", n);
return 0;
}
对于移位运算符,不能移负数位
比如:a<<-1,这是不被定义的
5.位操作符
5.1 &(按位与)
计算规则:对应的二进制进行计算(只要有0就是0,同时为1才为1)
比如:
-3的补码:11111111 11111111 11111111 11111101
5的补码: 00000000 00000000 00000000 00000101
-3 & 5 : 00000000 00000000 00000000 00000101(5)
5.2 |(按位或)
计算规则:对应的二进制进行计算(只要有1就是1,同时为0才为0)
比如:
-3的补码:11111111 11111111 11111111 11111101
5的补码: 00000000 00000000 00000000 00000101
-3 | 5 : 11111111 11111111 11111111 11111101
转化为原码(取反加1):10000000 00000000 00000000 00000011(-3)
5.3 ^(按位异或)
计算规则:对应的二进制进行计算(相同为0,不同为1)
比如:
-3的补码:11111111 11111111 11111111 11111101
5的补码: 00000000 00000000 00000000 00000101
13^5 : 11111111 11111111 11111111 11111000
转化为原码:10000000 00000000 00000000 00001000(-8)
5.4 ~(按位取反)
计算规则:对应的二进制进行计算(进行取反操作,符号位也是)
比如:~1
1的补码:00000000 00000000 00000000 00000001
按位取反:11111111 11111111 11111111 11111110
转化为原码:10000000 00000000 00000000 00000010(-2)
int main() {
int a = -3;
int b = 5;
printf("%d\n", a & b);
printf("%d\n", a | b);
printf("%d\n", a ^ b);
printf("%d\n", ~1);
return 0;
}
6.单目操作符
单目操作符:!,++,- -, *,+,-,~,sizeof,&(取地址)
sizeof不是函数,它的作用是打印数据类型占用的字节数。
sizeof(int) = sizeof int
函数不能省略括号,所以sizeof不是函数而是操作符
7.逗号表达式
逗号表达式就是用都好隔开的多个表达式,其中的结果等于最后一个表达式运算的结果
int main() {
int n = 0;
int c = (3 > 5, n++, 4);
printf("%d", c);
return 0;
}
8.操作符的优先级
优先级指的是,如果一个表达式包含多个运算符,哪个运算符应该先执行。各种运算符的优先级都有所不同
9.操作符的结合性
如果两个运算符的优先级一样,那么就看结合性来判断应该先执行哪个,根据操作符的左结合和右结合来决定执行顺序。