一.进制
计算机采用二进制来记录数据,二进制是一种数字表示方式
二进制数字每个数位上是0或者1,计算机中一个字节分成8个二进制位(bit)
十进制和二进制只是数字的两种表示方法
1.十进制和二进制之间的转换
(1)二进制转换成十进制
12345 = 1X10^4 + 2X10^3 +3X10^2 +4X10^1 +5X10^0
二进制数字每个数位有一个编号,最右边数位编号是0,向左每一位编号递增1,某个数位上的1转换成10进制的结果是2的数位编号次方
二进制转换成十进制的结果就是将二进制表示方式上每个1单独转换,再将转换结果求和
1001011 = 2^6 + 2^3 + 2^1 + 2^0
= 64 + 8 + 2 + 1
= 75
(2)十进制转二进制
方法一: 将10进制数字拆分成多个2的整数次方之和,然后将每个拆分的结果单独转换成2进制,最后把所有的结果合并
113 = 2^6 + 2^5 + 2^4 + 2^0
= 1000000 + 100000 + 10000 + 1
= 1110001
方法二: 除2取余法,将10进制数字不停除以2,直到结果为0,将所有的余数倒着写
113 1
56 0
28 0
14 0
7 1
3 1
1 1
0
将余数倒着写,结果为 1110001
通过以上方法得到的二进制表示形式叫做原码,而计算机保存数据使用的是补码
计算机表示有符号数据时,最高位用作符号位,0表示正,1表示负
整数的补码就是原码,负数的补码是相反数原码取反+1
C语言有取余运算符是 % ,用来获取除法运算的余数
2.八进制和十六进制
(1)八进制
将二进制的表示形式从右到左每三个数位分为一组,每组用一个0-7之间的数字代替,这样转换得到的结果就是该数字的八进制形式
1 110 001 = 161
八进制可以看成是二进制的简写形式,在C语言中不直接使用二进制,如果要表示二进制可以用八进制来代替,代码中可以直接使用八进制
C语言中数字默认是10进制,如果表示一个数字是八进制需要在数字前加0
printf函数打印整数的八进制对应的占位符是 %o
(2)十六进制
十六进制也是二进制的简写形式,比八进制更加常见。
将二进制的表示形式从右到左每四个数位分为一组,每组用一个0-9 a-f(10-15)之间的数字/字母代替,这样转换得到的结果就是该数字的十六进制形式
1111 0001 = f1
128+64+32+16+1 = 241
可以在代码中直接使用十六进制,但是需要在十六进制数字前加0x
printf函数打印整数的十六进制对应的占位符是 %x %X
二.运算符
运算符代表了计算机可以对数据进行的某种操作,也叫操作符
1.运算符的分类
按功能来分类:
算数运算符 --------- + - * / % ++ --
关系运算符 --------- == > < != >= <=
逻辑运算符 --------- && || !
位运算符 ---------- & | ~ ^ << >>
地址相关 ---------- & *
.....
按照操作数个数来分:
单目运算符 -------- 一个操作数
双目运算符 -------- 两个操作数
三目运算符 -------- 三个操作数 ? :
运算符有优先级,在一个表达式中优先级高的运算符先运算
2.算数运算符
赋值运算符(=)可以将右边的值赋值给左边,优先级较低,低于算数运算符。
自增(++)和自减(–)运算符用来对操作数进行加1/减1操作
他们都是单目运算符,每个运算符都有两种使用方法:前操作和后操作
前操作的优先级非常高,往往在一个表达式中最先执行
后操作的优先级非常低,往往在一个表达式中最后执行
注;不要在一个表达式中进行多次自增/自减运算,容易造成歧义
双目算数运算符(+ - * / %)可以和赋值运算符(=)组合形成复合赋值运算符(+= -= /= *= %=)
当我们希望将运算的结果保存到某个操作数就可以使用复合赋值运算符,比如:
a = a + b;
a += b;
复合赋值运算符的优先级和赋值运算符一样低
3.关系运算符
关系逻辑运算的结果是一个布尔值,布尔值只包含真(true)和假(false)
计算机中用1表示真,0表示假。所有的数字除了0表示假,其他都是真
关系运算的结果就是一个布尔值,== != > >= < <=
关系运算符的优先级低于算数运算符
注:如果对运算符的优先级不确定,可以使用小括号将希望先运算的部分括起来
4.逻辑运算符
! 是一个单目逻辑运算符,作用将一个布尔值取反
&&是逻辑与运算符,操作数应该是布尔值(逻辑表示式),运算规则如下
真 && 真 ----------- 真
真 && 假 ----------- 假
假 && 真 ----------- 假
假 && 假 ----------- 假
||是逻辑或运算符,操作数应该是布尔值(逻辑表示式),运算规则如下
真 || 真 ----------- 真
真 || 假 ----------- 真
假 || 真 ----------- 真
假 || 假 ----------- 假
逻辑与和逻辑或的优先级低于关系运算符,使用逻辑与和逻辑或可以组成复杂的逻辑表达式
逻辑与(&&)和逻辑或(||)具有短路特性,如果前一个表达式的结果已经可以决定整个表达式的结果,那么后面的表达式将不会被执行
5.位运算符
(1)位运算对操作数按二进制位进行操作 按位与(&)就是将操作数的每个二进制位进行与运算
3 & 5
= 0011 & 0101
= 0001
= 1
某个数与上1不变,与上0变为0,按位与能够将一个数字的某些位清0
char num;//将最低位和第2位清0
num & 11111010 = num & ~00000101
~的作用是将操作数按二进制位按位取反
(2)按位或(|)将操作数的每个二进制位进行或运算
3 | 5
= 0011 | 0101
= 0111
= 7
某个数或上0不变,或上1变为1,按位或能够将一个数字的某些位置1
char num;//将低2位置1
num | 00000011
(3)按位异或(^)将操作数的每个二进制位进行异或运算(相同为0,不同为1)
0 ^ 0 = 0
1 ^ 0 = 1
0 ^ 1 = 1
1 ^ 1 = 0
例:
3 ^ 5
= 0011 ^ 0101
= 0110
= 6
某个数异或0不变,异或1取反,按位异或能够将一个数字的某些位取反
char num;//将低3位取反
num ^ 00000111
口诀:与0清0,或1置1,异或1取反
(4)按位左移(<<)和按位右移(>>)将操作数整体按二进制位左右移动
unsigned char ch = 0x2c;// 00101100
ch<<2;//左移移出的高位丢弃,空出的低位补0
ch>>2;//无符号的数据右移移出的低位丢弃,空出的高位补0
char ch = 0x8c;
ch>>2;//有符号的数据右移移出的低位丢弃,空出的高补符号位
(5)地址相关运算符
&是取地址符,获取变量的存储地址,地址可以用%p作为占位符打印
*是解引用符,是取地址的反操作,可以通过地址获取地址上存储的数据
(6)三目运算符
C语言有唯一的一个三目运算符, 使用方法如下:
布尔值 ? 代码1 : 代码2
布尔值为真,执行代码1,布尔值为假,执行代码2
6.类型转换
(1)隐式类型转换
C语言中如果一个表达式中包含多个不同的数据类型,计算机会先将他们转换成同一种数据类型再进行运算
这个转换是自动转换的,也叫作隐式类型转换
转换规则:
如果不同数据类型所占空间大小不同,将所占空间小的类型转换成所占空间大的类型
如果不同数据类型所占空间大小相同,将整数类型转换成浮点类型,把有符号类型转换成无符号类型
(2)强制类型转换
在程序中任意给数据指定类型,这种方式叫做强制类型转换
语法:
(指定类型)数据;
强制类型转换不受任何规则的限制,可能造成数据丢失
强转的原理是计算机临时生成一个数据,新数据的数值来自于原数据,类型由程序指定。强转不会改变原数据
7.运算符优先级总结
优先级数字越小,优先级越高
优先级 | 运算符 |
---|---|
1 | () [] . -> |
2 | (强转) -(负号) ++ -- *(取值) &(取地址) ! ~ sizeof |
3 | * / % |
4 | + - |
5 | >> << |
6 | > >= < <= |
7 | == != |
8 | & |
9 | ^ |
10 | | |
11 | && |
12 | || |
13 | ? : |
14 | = += >>= &= |
15 | , |
注:逗号也是一个运算符,用于连接两个表达式,优先级低于赋值运算符,连接多个表达式后取后一个表达式的值
如果对运算符优先级不确定,就使用小括号