C语言知识点保姆级总结,这不得进你的收藏夹吃灰?!
拖了很久的C语言所学知识的简单小结,内容有点多,第一次总结也可能有错误或者不全面,欢迎随时补充说明!
第二天
1、计算机的基本构成
输入输出设备(键盘、鼠标)
CPU处理器:(控制器,运算器,寄存器)
存储器
程序
存储器:内存和外存
内存:工作存储器,容量较小,运行速度快,掉电数据会丢失
外存:长期保存数据,容量较大,运行速度慢,掉电数据不会丢失
寄存器:cpu内部的存储器,运行速度最快,容量非常小
2、什么是程序
程序:计算机能够识别的一组有序的指令
指令:计算机能够识别的操作
Hello.c和a.out那个是程序:a.out
3、程序的设计步骤
Vim(编辑)-------gcc(编译)------./a.out(运行/调试)
4、计算机的数据表示
非数值数据和数值数据
10 ------0000 1010
4.1、非数值数据
字符、图片、声音
‘a’ ‘A’
ASCII码表:规定了每一个字符以哪8位二进制数去表示
1字节= 8bit(位)
‘a’ = 97
‘A’ = 65
‘0’ = 48
‘\0’ = 0
所有的大写字母都比小写字母:小32
4.2 数值数据(进制转换)
可以直接进行运算的数据
二进制、八进制、十进制、十六进制
二进制: 0~1(逢二进1)
八进制:0~7(逢八进1)
十进制:0~9(逢十进1)
十六进制:0 ~9、a~ f(A~F)(逢16进1)
为了区分不同的进制:八进制前加0,十六进制前0x(0X)(0x7fa 0X7FA)
十进制:76 八进制:076 十六进制:0x76、0X76
4.3 进制转换
其他进制转十进制:(注意:从右往左:从0次幂开始)
二进制转十进制:1010 0101 = 1*2^0+1*2^2+1*2^5+1*2^7
八进制转十进制:076=6*8^0 + 7*8^1
十六进制转十进制:0xafc = 12*16^0+15*16^1+10*16^2
十进制转其他进制:
十进制转二进制:除2倒取余数
十进制转八进制:除8倒取余数
十进制转十六进制:除16倒取余数
二进制和八进制:(将每一个八进制数用三个bit的二进制数去表示)
(421)
0~7 (000 ~ 111)
- ----------000
- ----------001
- ----------010
- ----------011
- ----------100
- ----------101
- ----------110
- ----------111
0654:(转换为二进制: 110 101 100)
010 110 111:(转换为八进制:0267)
二进制和十六进制:(每一个十六进制可以用4位二进制数去表示)
(8421)
0 ~ F (0~15)(0000~1111)
0 -------0000
- -------0001
- -------0010
- -------0011
- -------0100
- -------0101
- -------0110
- -------0111
- -------1000
- -------1001
- -------1010
- --------1011
- --------1100
- --------1101
- --------1110
- --------1111
0xfad:(转换为二进制:1111 1010 1101)
大家可以练习下面几个题作为今天的学习成果:
实现其他进制转换为十进制:
1 1001 1110 先转换为十六进制: 0x19e = 14*16^0 +9*16^1+1*16^2
06543 = 3*8^0+4*8^1+5*8^2+6*8^3
0xfadc
十进制转二进制:987:转换为16进制或者8进制,然后在转换为二进制
八进制和十六进制转换为二进制:
0xa865 = 1010 1000 0110 0101
0763 = 111 110 011
(十六进制:用4个二进制去表示8421)
(八进制:用三个二进制去表示421)
二进制转换为八进制和十六进制:1100 1110 1110
110 011 101 110转换为八进制:06356
1100 1110 1110转换为十六进制:0xcee / 0XCEE
5、基本数据类型
关键字:系统预先定义好的,有特殊含义的,并且都是小写,不能重新定义
一共有32个:
数据类型:char、short、int、long、float、double、enum、union、struct、void
控制语句:if、else、for、do、while、switch、case、default、break、continue、goto
存储类型:auto、static、extern、register
const:只读
return:返回函数
signed:有符号数
unsigned:无符号数
sizeof:计算所占内存空间的大小:单位:字节
typedef:给一个已有的数据类型起别名
volatile: 防止编译器优化
标识符:程序员自己定义的,一般用来定义变量名,函数名,类型名
命名规范:(见名知意)
1、由数字、字母、下划线组成。
2、第一个不能为数字。
3、不能和关键字重名
5.1基本数据类型
32os:分别占据多少个字节:
字符型:char(1字节)
整型:int(4字节) short(2字节) long(4字节)
浮点型:float(4字节) double(8字节)
64os:
字符型:char(1字节)
整型:int(4字节) short(2字节) long(8字节)
浮点型:float(4字节) double(8字节)
注意:每一种数据类型所占的内存空间是不相同的,数据类型主要就是为了让我们合理的分配内存空间
5.2 有符号数和无符号数
有符号数(signed):有正数有负数(定义一个变量,默认是有符号的)
所有的数据都以补码的形式保存在计算机中
符号位:最高位表示该数据为正数还是负数(0表示正数,1表示负数)
- --------0000 1010
-10-------- 1000 1010
10+(-10) = 0
为了保证计算的正确性:计算机中保存数据时,以补码的形式保存数据的
正数:原码,反码,补码都是一样的
10--------原码:反码:补码:0000 1010
负数:
原码:直接转换为二进制,并且最高位表示符号位
反码:符号位不变,其他位取反(0变1,1变0)
补码:反码+1
-10 -------
原码: 1000 1010
反码: 1111 0101
补码: 1111 0110
知道一个数的补码,如何求得原码?
1111 0110问:他表示的是多大的数据;
- 补码的补码就是原码;
2、减1,符号位不变,取反
无符号数(unsigned):只有正数,并且都是数据位
5.3 字符型家族
值域范围:
Char(1字节)
unsigned char:
0000 0000 ------ 1111 1111 (0 - 255)
signed char:
有符号数:最高位要用来表示:符号(0正,1负)
1000 0000------ 0111 1111 (-128~127)
考点!超过这个范围:转圈去数
Unsigned char c = 260;
printf(“%d\n”,c); // 4
Signed char a = 130;
Printf(“%d\n”,a); // -126
5.4 整型家族
Int (4字节 == 32bit)
unsigned int :
0000 0000 0000 0000 0000 0000 0000 0000 ------1111 1111 1111 1111 1111 1111 1111 1111
(0 ~ 2^32-1)
Signed int:
1000 0000 0000 0000 0000 0000 0000 0000 ----- 0111 1111 1111 1111 1111 1111 1111 1111
(-2^31 - 2^31-1)
5.5 浮点型家族
Float(单精度浮点数):表示6~7位有效数据
%f(默认输出小数点后6位)
Double(双精度浮点数):表示15~16位有效数据
%lf(默认输出小数点后6位)
如果想要输出小数点后n位(%.nf)
注意:
Printf(“原样输出的内容+格式化符”,输出表);
注意:格式化符要和输出表一一对应;
6、转义字符
(1字节)
见到转义字符时:认识并且会用
“ af\79\\\n” = 7
“ af\74\\\n” = 6
7、常量
定义:在程序运行期间,不会也不能被改变的量
7.1字符常量
‘a’ ’A’ ‘b’
7.2 整型常量
二进制:1010
八进制:076
十进制:99 -2
十六进制:0xaf 0X6FC
(默认情况下,为有符号数:int、short、long)
无符号的int:66U
长整型:66L
无符号的长整型:66UL
7.3 浮点型常量
小数:3.14 10000(浮点型常量也包括整形常量)
指数:10000 = 1*10的4次方 1e+4 1e-4
//error:(1*10^4)
%g:选择小数或者指数比较短的一种形式进行输出
^ :异或(位运算符),并不是指数
7.4 字符串常量
“hello” “hi”
字符串以‘\0’结尾
7.5 标识常量(宏)
宏只是一个单纯的替换!!!
宏:#define 宏名 表达式
注意:
1、宏名一般用大写表示,小写也可以,因为要和普通的变量区分开来,所以用大写
2、宏后没有分号
案例:求一个圆的周长和面积
宏定义一个PI,给定一个半径
宏函数:(既有宏的特点,又有函数的特点)
#define 函数名(形参) 函数体
#define ADD(a,b) a+b
案例1:实现两个数的求和
案例2:
案例3:
案例四:
注意:宏只是一个单纯的替换,他并不会考虑运算符优先级的问题,因此,需要给每个形参,以及整个表达式,都加上括号。
第三天
1、变量
定义:就意味着要在内存空间中开辟空间
如何定义一个变量?
<存储类型> 数据类型 变量名;
存储类型:决定了开辟的空间在内存空间中的哪个分区
数据类型:决定了开辟的内存空间的大小
变量名:开辟的内存空间的名字
存储类型:auto、static、extern、register
1.1局部变量
定义在函数体(任何函数体内)内的变量;
1.2 全局变量
定义在函数体外的变量
1.3 存储类型
存储类型:auto、static、extern、register
auto:修饰局部变量,修饰的变量存储在栈区
extern:修饰全局变量,修饰的变量存储在静态区
static:既可以修饰局部变量,也可以修饰全局变量,修饰的变量存储在静态区
register:修饰局部变量,存储在寄存器中;
1.4 初始化
初始化:在定义变量的时候就进行赋值了
1、int a = 10;//初始化
2、int a;
a = 10;//赋值
总结
- 全局变量没有进行初始化时,他的值为0
- 局部变量没有进行初始化时,他的值为随机值
(定义变量时,尽量给他一个初始值,避免出现随机值)
存储类型:auto、static、extern、register
auto:修饰局部变量,修饰的变量存储在栈区
register:修饰局部变量,修饰的变量存储在寄存器中,建议将变量存储在寄存器中,提高运行速度,但是寄存器中的内存空间很小,因此,当用register修饰时,如果寄存器中已满,变量就会存储在栈区
extern:修饰全局变量,修饰的变量存储在静态区
程序可以由多个.c构成,但是只能有一个main函数
作用:告诉编译器,该变量已经在其他文件中定义过了
Static:即可以修饰全局变量,也可以修饰局部变量
1、修饰局部变量时,延长局部变量的生命周期,如果局部变量没有初始化,其值为0;如果初始化了,则只能初始化一次;
(延长了生命周期,但是并没有延长作用域!!)
2、修饰全局变量时,限制作用域,该变量只能在本文件内使用
1.5 生命周期和作用域
1.5.1生命周期:
从开辟空间一直到释放空间
1.5.2 作用域
使用的范围
局部变量:
生命周期:从定义开始,到模块结束(距离它最近的大括号)释放空间
作用域:大括号内
Static修饰的局部变量:
生命周期:从定义开始,到程序结束
作用域:大括号内
全局变量:
生命周期:从定义开始,到程序结束
作用域:整个程序
Static修饰的全局变量:
生命周期:从定义开始,到程序结束
作用域:本文件内
2、数据类型转化
2.1 强制类型转化(我们自己去转的)
2.2隐式类型转换(编译器去转的)
横向箭头:
不管有没有进行混合运算,都会进行转换;
注意:char、short都当做int来用
注意:float当做double来用
纵向箭头:
只有进行了混合运算,才会进行转换;
案例:
3、运算符
单算移关与,异或逻条赋
单目运算符、算术运算符、左移、右移、关系运算符、按位与、异或、按位或、逻辑运算符、
条件运算符、赋值
3.1 算术运算符
+ - * / % ++ --
%:取余
注意:不能用于浮点数
++在前:先自加,在赋值
++在后:先赋值,在自加
注意:如果a++或者++a,单独成立一条语句,都相当于给a加1;
3.2 关系运算符
> < >= <= == !=
关系运算符:比较两者之间的关系,结果为(真1或者假0)
//注意 (0 < a < 5) error
等号的书写:将常量写在等号的左边
3.3 逻辑运算符
&& || !
&&
表达式1 && 表达式2
&&截断法则:有一个为假,结果就为假;前一个为假,后面就不在进行运算了
||
表达式1 || 表达式2
截断法则:有一个为真,结果就为真,前一个为真,后面就不在进行运算了
3.4 sizeof运算符
sizeof:计算所占内存空间的大小:单位:字节
sizeof(数据类型)
sizeof(变量名)
3.5 三目运算符
表达式1 ? 表达式2 :表达式3
判断表达式1是否成立,如果成立,就将表达式2的值作为整个表达式的值,否则,就将表达式3的值作为整个表达式的值
3.6 逗号运算符
表达式1,表达式2,表达式3,。。。。。,表达式n
从左往右,依次去执行每个表达式,最后将表达式n的值作为整个表达式的值
注意:逗号运算符的优先级是最低的,因此在使用时要加上括号
注意:a+1,并没有改变a的值
3.7 位运算符
& | ~ ^ << >>
3.7.1 按位与(&)
都为1,才为1,有一个为0,就为0
0000 1010
0000 0010
--------------------------------------------
0000 0010
案例:将1001 0010的0~2位清零
1001 0010
& 1111 1000 ~(0000 0111)== ~(7)
1001 0000
3.7.2 按位或(|)
都为0,才为0,有一个为1,就为1
1001 0011
| 0100 1010
-------------------------------------------------
1101 1011
案例:将1101 0101的0~2 位修改为010
1101 0101
& 1111 1000
--------------------------------------
1101 0000
| 0000 0010
-------------------------------------
1101 0010
要修改某几位时,先用&的方法,清零,在用|的方法置1
3.7.3 按位取反(~)
1变0, 0变1
~(1001 0010) == 0110 1101
3.7.4 异或(^)
相同为0,不同为1
1010 0110
^ 0100 1010
-----------------------------------------------------
1110 1100
3.7.5左移(<<)
Unsigned:
0000 0001 << 2
高位丢弃,低位补0
0000 0100 ------------------4
Signed:
负数:-1 <<2
原码:1000 0001
反码:1111 1110
补码:1111 1111
高位丢弃,低位补0
补码:1111 1100
反码:1000 0011
原码:1000 0100------------ -4
3.7.6右移(>>)
Unsigned:
正数
0000 0100 >>2
低位丢弃,高位补0:
0000 0001---------------------1
Signed:
负数:
-4 >> 2
符号位不变,低位丢弃,高位补1
原码:1000 0100
反码:1111 1011
补码:1111 1100
1111 1111
反码:1000 0000
原码:1000 0001------------- -1
总结
左移:
无符号数:高位丢弃,低位补0
有符号数:符号位不变,高位丢弃,低位补零
右移:
无符号数:低位丢弃,高位补0:
有符号数:符号位不变,低位丢弃,高位补(0正,1负)
第四天