一、操作符的分类
• 算术操作符: + 、- 、* 、/ 、%
• 移位操作符: > • 位操作符: & | ^ `
• 赋值操作符: = 、+= 、 -= 、 *= 、 /= 、%= 、>= 、&= 、|= 、^=
• 单⽬操作符: !、++、--、&、*、+、-、~ 、sizeof、(类型)
• 关系操作符: > 、>= 、< 、<= 、 == 、 !=
• 逻辑操作符: && 、||
• 条件操作符: ? :
• 逗号表达式: ,
• 下标引⽤: []
• 函数调⽤: ()
• 结构成员访问: . 、->
二、进制转换
这是十进制每位的权重:
这是二进制每位的权重:
十进制转二进制:
二进制转八进制:
八进制的一位数字,转换成二进制,是二进制的三位数字。
注:
二进制转16进制:
16进制的每一位数字,转换成二进制,是二进制的四位数字。
注:0b后面加1或0表示二进制数。
十六进制表示的时候前面加0x。
0开头的数字,会被当做八进制。
三、原码,反码,补码,整数在内存中的存储
整数的二进制表示方法有三种,即原码,反码,补码。
有符号整数的三种表示方法均有符号位和数值位两部分,二进制序列中,最高位的一位是被当做符号位,剩余的都是数值位。
符号位都是用0表示正,用1表示负。
正整数的原码,反码,补码都相同。
负整数的三种表示方法各不相同。
原码:直接将数值按照正负数的形式翻译成二进制得到的就是原码。
如:1的原码:
00000000000000000000000000000001(一个int型数据占4个字节,32个比特位)
反码:原码符号位不变,其他位按位取反得到。
如:1的反码:
01111111111111111111111111111110
补码:反码+1得到补码。
如:1的补码:
01111111111111111111111111111111
补码得到原码也是可以使用符号位不变,其他位取反,加一的操作。
对于整形来说,数据存放内存存放的是补码。
四、移位操作符
<< 左移操作符,>> 右移操作符
注:移位操作符的操作数只能是整数。
左移操作符
左边抛弃,右边补零。
如:
右移操作符
1.逻辑右移:左边用0填充,右边丢弃
2.算数右移:左边用原该值的符号位填充,右边丢弃。
逻辑右移:
算术右移:
警告:对于移位运算符,不要移动负数位,这个是标准未定义的。
五、位操作符:&、|、^、~
& //按位与
只要有0则为0,同时为1才是1。
输出结果:3
| //按位或:只要有1就是1,两个同时为0才是0。
^ //按位异或:相同为0,相异为1。
~ //按位取反:1变0,0变1。
他们的操作数必须是整数。
六、单目操作符:!、++、--、&、*、+、-、~ 、sizeof、(类型)
单⽬操作符的特点是只有⼀个操作数。
七、逗号表达式
逗号表达式,从左向右依次执⾏。整个表达式的结果是最后⼀个表达式的结果。
八、下标访问[]、函数调用()
下表访问操作符:操作数:一个数组名+一个索引值
int arr[10];//创建数组
arr[9] = 10;//实⽤下标引⽤操作符。
[ ]的两个操作数是arr和9。
函数调用操作符:第一个操作数是函数名,剩余的操作数是传递给函数的参数。
九、结构成员访问操作符
结构体成员的直接访问是通过(.)操作符访问的,点操作符接受两个操作数。
使用方式:结构体变量.成员名
有时候我们得到的不是⼀个结构体变量,⽽是得到了⼀个指向结构体的指针。
使⽤⽅式:结构体指针->成员名
十、操作符的属性,优先级,结合性
• 圆括号( () )
• ⾃增运算符( ++ ),⾃减运算符( -- )
• 单⽬运算符( + 和 - )
• 乘法( * ),除法( / )
• 加法( + ),减法( - )
• 关系运算符( < 、 > 等)
• 赋值运算符( = )
由于圆括号的优先级最⾼,可以使 比特就业课 ⽤它改变其他运算符的优先级。
十一、整形提升
表达式中的字符和短整型操作数在使用之前被转换成普通整形,这种转换成为整形提升。
有符号整形提升是按照变量的数据类型的符号位来提升的。
无符号整形提升,高位补0。
即:有1补1,有0不0。
//负数的整形提升
char c1 = -1;
变量c1的⼆进制位(补码)中只有8个⽐特位:
1111111
因为 char 为有符号的 char
所以整形提升的时候,⾼位补充符号位,即为1
提升之后的结果是:
11111111111111111111111111111111
//正数的整形提升
char c2 = 1;
变量c2的⼆进制位(补码)中只有8个⽐特位:
00000001
因为 char 为有符号的 char
所以整形提升的时候,⾼位补充符号位,即为0
提升之后的结果是:
00000000000000000000000000000001
//⽆符号整形提升,⾼位补0
十二、内存地址的理解
第一列数字是十六进制数字,代表地址32位或64位环境下的地址。
第二列数字是存储在内存中的数据,每一个地址对应一个字节(8个比特位),类型是十六进制。存储在计算机中是以二进制存储的。如第一列中的 ‘80’在内存中以‘1000 0000’的形式存储。
第三列数据是对第二列数字的解析,是第二列十六进制数字在ASCII码表上的对应值。如图中十六进制数字28对应的是ASCII码表中的‘(’。
十三、大小端字节序和字节序的判断
超过一个字节的数据在内存中存储的时候,就有存储数据的问题。按照不同的存储顺序,有大端字节序存储和小端字节序存储。
大端存储模式:高位保存于低地址处,低位保存于高地址处。(高位保低,低位保高)
小端存储模式:高位保存于高地址处,低位保存于低地址处。(高位保高,低位保低)
常用的x86结构是小端模式。
十四、浮点数在内存中的存储
任意一个二进制浮点数V可表达成下面的形式 :
V = (−1)^S * M ∗ 2^E
其中, (−1)^S表示符号位,S取1或0,决定数字的正负性。M表示有效数字,1≤M<2。2^E表示指数位。
举例子:十进制的5.0,写成二进制是101.0,相当于(-1)^1 * 1.01 * 2^2。S=1,M=1.01,E=2。
对于float类型(4个字节,32个比特位)浮点数, 最高的一位存储符号位S,接着8个位存储指数E,剩下的23位存储有效数字M。
对于double类型(8个字节,64个比特位)浮点数, 最高的一位存储符号位S,接着11个位存储指数E,剩下的52位存储有效数字M。
浮点数存的过程:
1.保存M:
前文说过,1≤M<2,则M可写成1.xxxxxx的形式,其中xxxxxx表示小数部分,存储的时候舍去前面的1,只保留小数部分。
2.保存E:
E为一个无符号整数,它的取值范围为0-255;如果E为11位,它的取值范围是0-2047.科学计数法中,E可能为负数,所以保存E的时候,要对它加上一个值。对于8位的E,这个中间值是127,对于11位的E,他的中间值为1023。例如2^10的E是10,保存成32位浮点数时,将10加上127=137,转化为二进制,是10001001,再存入内存中。
浮点数取的过程,分为三种情况:
E不全为零或不全为1
这时就按照保存E时的方式,倒着来:先将E的值减去127(或1023),然后得到真实值,再将有效数字M前加上第一位的1。
比如:0.5的二进制形式为0.1,由于规定整数部分必须为1,即将小数点右移一位,则为1.0*2^(-1),E=-1,加上127,等于126,转换成二进制,是0111 1110,然后M=1.0,去掉最前面的1,则是0,补齐为23位,则是00000000000000000000000,其二进制表示形式为:
0 01111110 00000000000000000000000
S E M
E全为0
这时,浮点数的指数E等于1-127(或者1-1023)即为真实值,有效数字M不再加上第一位的1,而是还原为0.xxxxxx的小数,。这样做是为了表示±0以及接近于0的很小的数字。
E全为1
这时,如果有效数字M全为0,表示±无穷大(取决于S)。
十五、浮点数的比较方法
有些浮点数无法精确保存,在作比较的时候不能直接用‘==’号进行比较,结果可能会出现错误。
比较方法:使用abs()函数(求绝对值),需要自己给一个精度,如果两个浮点数的差满足这个精度,则默认两个数相等。
if(abs(f-5.6)<=0.000001)
{
……
}