1.操作符的分类
• 算术操作符: + 、- 、* 、/ 、%
• 移位操作符: >
• 位操作符: & | ^
• 赋值操作符: = 、+= 、 -= 、 *= 、 /= 、%= 、>= 、&= 、|= 、^=
• 单⽬操作符: !、++、--、&、*、+、-、~ 、sizeof、(类型)
• 关系操作符: > 、>= 、< 、<= 、 == 、 !=
• 逻辑操作符: && 、||
• 条件操作符: ? :
• 逗号表达式: ,
• 下标引⽤: []
• 函数调⽤: ()
2.二进制和进制转换
2进制、8进制、10进制、16进制是数值的不同表达形式
2进制:1111 8进制:17 7*8的0次方加1*8的1次方 10进制:15 16进制:F
2进制数字都是0~1组成的
8进制都是0~7的数字组成的
10进制的数字都是由0~9的数字组成
16进制的数字是0~9,a~f的数字组成
二进制满2进一
假设输入的10进制数字是125,一次除以2 然后依次是125 62 31 15 7 3 1 0 余数依次是 1 0 1 1 1 1 1,所以10进制的125转换的2进制是:1111101 20用二进制来表达就是10100
2进制 0 1 1 0 1 0 1 1 8进制 1 5 3 从二进制的右边开始换算成八进制,每3个换算一次 不足3个的2进制位直接换算, 2进制的01101011换算成8进制的数字就是153 注意:0开头的数字,会被当做8进制
2进制 0 1 1 0 1 0 1 1 16进制 6 b 从二进制序列的最右边开始转换 每4个数字转换一次,不足4个数字的二进制直接转换 二进制右边的1011转换为10进制的数就是11,在16进制中用b表示 二进制左边的0110转换为10进制就是6,在16进制中用6表示 2进制的01101011转换成16进制0x6b, 16进制表示的时候前面加上0x
如果进行8进制转换成2进制甚至16进制转化为2进制只需要用反思路就可以算出
8进制位中的3换算成2进制就是011
8进制位中的5换算成2进制就是101
16进制的0x47转换为2进制就是01000111,因为7用二进制来表达就是0111,4用二进制来表达就是0100
8进制的047转换为2进制就是100111,因为8进制的7转换为2进制就是111,4转换板为二进制就是100
8进制是以二进制的三个数为一个单位的
16进制是以二进制的四个数为一个单位的
3.原码反码补码
整数的二进制表达形式有3种,即原码、反码和补码
有符号整数的三种表达方式均有符号位和数值位两部分,
2进制位中,最高位的1位是被当做符号位,剩余的都是数值位
符号位都是0表示正,1表示负
一个整型占的是4个字节,10占了8个字节,也就是32个bit位
正整数的原码反码补码都相同
负整数的三种表示方式个不同
原码:直接将数值按照正负数的形式翻译成二进制得到的就是原码
反码:将原码的符号位不变,其他位依次按位取反就可以得到反码
补码:反码+1就是补码----仅针对于负数
负数的反码除了开头的符号位不改变,其他的0变成1,1变成0
int a =10
原码:00000000000000000000000000001010
反码:00000000000000000000000000001010
补码:00000000000000000000000000001010
int a =-10
原码:10000000000000000000000000001010
反码:11111111111111111111111111110101
补码:11111111111111111111111111110110
对于负数,原码反码补码是要计算的,但是正数的原码反码补码都相同
原码取反得到反码,+1得到补码
补码-1取反得到原码,补码取反+1也能得到原码
11111111111111111111111111110110--补码
10000000000000000000000000001001--反码--补码取反
10000000000000000000000000001010---+1==原码--反码+1
数据存放在内存中的其实是补码
整数在内存中存储的其实是补码
原码得到补码和补码得到原码都是取反+1
1+(-1)用原码算的话得出来的数是-2
但是用补码算的话就是0
计算的时候都是用补码
4.移位操作符
<<左移操作符
>>右移操作符
注意:操作符的操作数只能是整数
移动的是存纯在内存中的二进制位---补码
左移规则:左边抛弃,右边补0
整数 int main() { int a = 10;//注意,移动的是存纯在内存中的二进制位---补码 int b = a << 1;//a向左移动2位 //10的二进制是1010 //10放到a里面存储,4个字节,32个比特位 //00000000000000000000000000001010----10的二进制数 //a向左移动一位,最左边的被挤出去了,最右边就补上一个0 //00000000000000000000000000010100----最后打印的b就是20 printf("%d\n", b);//输出结果是20 printf("%d\n", a);//结果仍然是10 return 0; } 负数 int main() { int a = -1; //10000000000000000000000000000001----- -1的原码 //11111111111111111111111111111110----- 取反 //11111111111111111111111111111111----- +1---- -1的补码 int b = a << 1; //移位后 //11111111111111111111111111111110---b的补码 //10000000000000000000000000000001---取反 //10000000000000000000000000000010---+1---b的原码---- -2 printf("b=%d\n", b);//打印的是b的原码-2 printf("a=%d\n", a);//-1 return 0; }
右移规则:首先右移运算分两种
1.逻辑右移:左边的用0填充,右边丢弃
2.算术右移:左边用原该值的符号填充,右边的丢弃
到底采用逻辑右移还是算术右移,取决于编译器
通常采用的都是算术右移
左边用原该值的符号填充,右边的丢弃
int main() { int a = -10; //10000000000000000000000000001010---原码 //11111111111111111111111111110101---取反 //11111111111111111111111111110110---补码 //采用算术右移,左边填充原来该值的符号,右边的丢弃 //11111111111111111111111111111011--右移后的补码 //10000000000000000000000000000100--取反 //10000000000000000000000000000101--+1--原码 //右移后的就是-5 int b = a >> 1; printf("a=%d\n", a);//-10 printf("b=%d\n", b);//-5 return 0; }
C语言---操作符详解(2)https://developer.aliyun.com/article/1544301