郝斌C语言详细笔记附源代码

上传人:无*** 文档编号:124226964 上传时间:2022-07-24 格式:DOC 页数:125 大小:6.13MB
收藏 版权申诉 举报 下载
郝斌C语言详细笔记附源代码_第1页
第1页 / 共125页
郝斌C语言详细笔记附源代码_第2页
第2页 / 共125页
郝斌C语言详细笔记附源代码_第3页
第3页 / 共125页
资源描述:

《郝斌C语言详细笔记附源代码》由会员分享,可在线阅读,更多相关《郝斌C语言详细笔记附源代码(125页珍藏版)》请在装配图网上搜索。

1、郝斌老师的C语言:课堂讲解全程动手敲代码,讲解细致,对于重要知识点的讲解不厌其烦,是一个难得的C语言入门教程。在这里对老师的辛勤付出表示感谢。郝斌c语言视频教程概述:课程计划为什么学习c语 言:Fortran语言主要用于科学计算,在第三代语言中,以1980年为分水岭,分为结构化和面向对象语言。Basic语言是vb的前生,pascal语言一般是用于教学。C语言是最重要的,其他的语言一般很少用了。结构化的代表语言是c语言。结构化语言的数据和操作是分离的,导致在写大项目的时候,会出现各种各样莫名其妙的问题。在面向对象的语言中c+是最复杂的语言。由于c+语言太复杂,sun公司对c+进行了改装,产生了j

2、ava语言。而c#是由微软开发的,和java相似,几乎一模一样。在高级语言的执行速度上,c是最快的,c+其次,而java和c#是最后的。Java和c#流行,主要的一个原因是可以跨平台。C语言的发展和过程:C语言的特点:优点:代码量小,速度快,功能强大。缺点:危险性高,开发周期长,可移植性弱。危险性高:写同一个程序,在java中会报错,而在c中不会报错,为什么呢,因为c认为程序你想怎么写就怎么写,c语言认为你写的程序不是很离谱,他都认为你写的这个程序有特殊的含义。可以直接通过,而java则不可以。开发周期长:c语言是面向过程的语言,面向过程的语言的特点就是在开发大项目的时候,很容易崩溃,好比盖大

3、楼,C语言还要造大量的砖块、钢筋等结构原材料,而C+ C# JAVA则进行了一定的继承封装等操作,相当于原材料直接给你,你只需要用它盖楼即可。现在市场上的语言分三块C/c+:单纯的学习c是什么都做不了的。JavaC#可移植性不强:这是针对java来说的,因为java的可移植性太强了,所以就感觉说c的可移植性不强。金山公司最主要是靠wps办公软件来发展的。Wps是c语言开发的,其安装包比Office少了10多倍。三大操作系统:windows,unix,linuxWindows内核是c语言写的,而外壳是c+写的。Java永远不可能写操作系统。因为java运行速度太慢了。而linux和unix都是纯

4、c写的。操作系统控制了硬件,如果说操作系统的运行速度慢,那么当我们在运行软件的时候,运行速度会更慢。为什么使用c语言写操作系统呢,首先是因为c的运行速度快,然后是因为c可以直接控制硬件,而其他语言不可以。没有指针的语言是不能直接访问硬件的。C语言的应用领域:驱动一般是用c和汇编来写的。数据库一般是用c和c+来写的C语言的重要性: 虽然应用场合相对较窄,但贴近系统内核,较底层。病毒最基本的是要感染系统,数据结构,c,c+这三门语言是必须要学习的。牛人牛语:怎样学习c语言要将编程当成一项事业来经营,而不是糊口的工具。多思考,多上机。 不能光看,光听,而要排错,调试。在犯错误中成长。参考资料王爽写的

5、c+也很不错学习的目标:掌握简单的算法-解决问题的方法和步骤。熟悉语法规则。能看懂程序并调试程序。C语言的关键字: C语言程序的格式:一定要养成良好的习惯:代码规范 边写边保存 ,括号成对出现,应用空格VC6.0软件操作:新建 保存 关闭(关闭空间).cpp是原始文件,可单独拷贝到其它电脑。第二讲:(14)c语言编程必备知识1. Cpu,内存条,硬盘,显卡,主板,显示器之间关系。Cpu不能直接处理硬盘上的数据,必须要先调入内存2. Hello word程序是如何运行起来的。3. 什么是数据类型数据类型-数据的分类,对编程而言,首要考虑问题是数据的输入和存储。可以分为A:基本数据类型:整型整型i

6、nt -4字节 一字节byte = 8 位bit短整型short int-2长整型long int-8浮点型单精度浮点数float:存储范围小 -4双精度浮点数double:存储范围大-8Float 和 Double 都不能保证将小数完全准确保存。字符char:c语言中是没有字符串string-1 (区别于JAVA、C#中有string且C#中 char为2字节)B:复合类型:就是把基本类型拼凑在一起结构体枚举 - 实用共用体基本淘汰4什么是变量变量的本质是内存中一段存储空间。Int I; i=5; I 是变量,程序向系统申请了一个内存单元,在程序运行中,i的值可以改变,但程序结束后,其所占的

7、空间不是释放,而是被系统收回权限。5 Cpu,内存条,vc+6.0,操作系统之间的关系。6 变量为什么必须初始(即赋值)软件运行与内存关系(垃圾数据-9868598658)1. 软件在运行前需要向操作系统申请存储空间,在内存空间足够空闲时,操作系统将分配一段内存空间并将该外存中软件拷贝一份存入该内存空间中,并启动该软件运行。2. 在软件运行期间,该软件所占内存空间不再分配给其他软件。3. 当该软件运行完毕后,操作系统将回收该内存空间(注意:操作系统并不清空该内存空间遗留下来的数据),以便再次分配给其他软件使用。操作系统一门课中系统分配表中会讲到,用1标记表示内在是被占用的,用0标记表示是空闲的

8、。综上所述,一个软件所分配到的空间中极可能存在着以前其他软件使用过后的残留数据,这些数据被称之为垃圾数据,所以通常情况下我们为一个变量,为一个数组,分配好存储空间之前都要对该内存空间初始化。7 如何定义变量数据类型 变量名称 = 赋予的值;等价于数据类型 变量名;变量名 = 要赋予的值;举例子:int i = 3; 等价于 int i; i = 3;Int i,j;等价于 int i;int j;Int i,j=3 等价于 int i; int j;j=3;Int I =3, j = 5;等价于 int i; int j; I = 3;j = 5;8 什么是进制 逢几进一我们规定八进制前面加0

9、(零),十六进制前面加0x。常用计数制对照表:Printf的基本用法:9 常量在c中是如何表示的当个字符使用单引号括起来,多个字符串使用双引号括起来(指针、数组)。在c中,默认是double类型的。在后面加F表示当做float来处理,否则会有警告提示 -丢失部分字节。10 常量以什么样的二进制代码存储在计算机中?编码:整数是以补码的形式转换为二进制代码存储在计算机浮点数是以ieee754标准转换为二进制代码存储字符本质实际是与整数的存储方式相同,ASII码标准。第三次课:代码规范化可以参考林锐高质量c/c+编程代码的规范化非常的重要,是学习一门编程语言的基础,代码可以允许错误,但不能 不规范。

10、例如:成对敲括号 ()加空格于 运算符和数字之间 I = 1 + 2;加缩进 分清上下级地位。换行-进行功能区域分隔 or 括号单独成一行。代码规范化的好处1:整齐,别人和自己都容易看懂。2:代码规范了,代码不容易出错。3:一般的程序可以分为三块:a: 定义变量b:对变量进行操作c: 输出值什么是字节存储数据的单位,并且是硬件所能访问的最小单位。内存中存储的最小单位是位bit(0或1),但是硬件控制的时候不能精确到位,只能精确到字节(8位),是通过地址总线来控制的,而精确到位是通过软件来控制的,叫做位运算符来精确到位的。1字节 = 8 位 1K = 1024 字节 1M = 1024 K 1G

11、 =1024 M 1T = 1024 G 2G的内存条的总空间:2 *1024 * 1024 *1024 * 8 =4*1032不同类型数据之间相互赋值的问题不同数据类型之间最好不要相互转换。如果需要明白这个知识点,那么需要明白补码。什么是ASCII码以char定义变量的时候,只能使用单引号括起一个字符才是正确的。在上图中注释的最后一样是重复定义了ch的值,是错误的,而下面的ch = c是指把c赋值给ch,是正确的。上图中输出的值是98(将字符以整数%d的形式输出)Ascll码规定了ch是以哪个值去保存,ascii码不是一个值,而是一种规定,规定了不同的字符是以哪个整数值去表示。其它规定还有G

12、B 2312 UTF-8等。字符本质上与整数的存储方式相同【字符的存储】基本的输入和输出函数的用法:第三次课Printf()将变量的内容输出到显示器上。四种用法输什么是输出控制符,什么是非输出控制符输出控制符包含如下:Printf为什么需要输出控制符:01组成的代码可以表示数据也可以表示指令。必须要有输出控制符告诉他怎么去解读。如果01组成的代码表示的是数据的话,那么同样的01代码组合以不同的格式输出就会有不同的输出结果,所以必须要有输出控制符。在上图中,int x =47,如果前面加0(零)048表示的是八进制,如果前面加0x(零x)0X47则表示的是十六进制,而在输出的时候,则是o(字母o

13、)表示八进制,ox(字母o,x)表示十六进制。非输出控制符:非输出控制符在输出的时候会原样输出。Scanf()通过键盘将数据输入到变量中有两种用法:示例:非输入控制符:在输入的时候也会原样输入。但是强烈建议:在使用scanf的时候,不使用非输入控制符。给多个变量赋值:需要记住,非控制符需要原样输入。如何使用scanf编写出高质量代码运算符:算术运算符:加(+),减()乘(*)除(/)取余(%)关系运算符:, =, , 关系逻辑赋值。取余的结果的正负只和被除数有关。第四节流程控制(第一个重点):1 什么是流程控制程序代码执行的顺序。2 流程控制的分类顺序执行选择执行定义:某些代码可能执行,可能不

14、执行,有选择的执行某些代码。分类:ifIf最简单的用法:如果想控制多个语句的执行或者不执行,那么需要使用括起来。3.ifelse的用法:ifelse ifelse的用法:C错误的ifelse ifelse语句:在上图中,当执行到哈哈那句时,下面的else将会被算作另外一个语句来执行,而在我们的c语言中,没有以else开头的语句。所以会出错。If 实例:If常见的问题:变量的替换:求三个数字的大小:C语言常见误区:纸老虎素数:只能被1和自己整除的数,如1,5,9等。回文数:正着写和倒着写一样的数。如1221,121,等编程实现求一个十进制数字的二进制形式:求一个数字的每位是奇数的数字取出来组合形

15、成的新数字。求一个数字到过来的数字。1:如果不懂,那么就看答案。看懂答案在敲。没错误了,在尝试改。如何看懂一个程序:1. 流程:2. 每个语句的功能:3. 试数:对一些小算法的程序:1. 尝试自己编程结局。2. 解决不了,看答案。3. 关键是把答案看懂。4. 看懂之后尝试自己修改程序,且知道修改之后程序的不同输出结果的含义。5. 照着答案去敲6. 调试错误7. 不看答案,自己独立把程序编出8. 如果程序实在是彻底无法了解,就把他背会。 空语句的问题: 在上图中,最终的结果会是AAAA,BBBB,程序也不会报错,为什么呢,因为在程序执行的时候,会在;哪里认为是一个空语句。也就是说,如果if成立,

16、那么执行空语句。If常见错误解析(重点)上面这个程序是错误的,为什么呢,在该程序中,总的有4个语句,而在以else开头的那个语句中是有错误的,因为在c语言中是没有以else开头的这种语法。在上面这个程序中,最终的值是AAAA,虽说后面的31也满足条件,但是当32满足条件后,该if语句就会终止,后面的语句是不会在执行的。 既然7行要写表达式,就要写if。循环的定义、分类。定义:某些代码会被重复执行。分类:for while dowhile 在上图中,先执行1,在执行2,2如果成立,标志着循环成立,那么在执行4,最后在执行3,3执行完后代表一次循环完成,然后在执行2.以此类推。1永远只执行一次。+

17、I 等价于 i+1求1-10的所有奇数的和:求1-12之间的所有能被3整除的数字之和: For所控制的语句:在上图中,for默认只能控制一个语句,但是如果要控制多个语句时候,那么需要使用把语句括起来。求1+1/2+1/3.1/100的和在上图中,重点是强制数据类型转换也就是(float)(i)那句:如果把print那句换为下面这句会怎么样呢:也是错的,为什么呢,因为i是整型,1也是整型,所以不管你怎么转换也是整型啊,如果想要这样写的话,那么我们需要把1改成1.0也可以的。也就是:试数详细步骤举例:浮点数存取:求1-100之间所有奇数的和:求1-100之间的奇数的个数: 求1-100之间奇数的平

18、均值: 求1-100之间的奇数之和,在求1-100之间的偶数之和:多个for循环的嵌套使用:整体是两个语句。上图中,先执行1,在执行2,如果2成立,执行4,在执行5,如果5成立执行A,在执行6,在执行5,如果5不成立,意味着里面的循环结束,然后执行3,在执行2,如果2成立又执行4,在执行5,如果5成立在执行6,在执行5,如果5不成立,在执行3,在执行2,如果2不成立,意味着本次循环结束,在执行B,在上图中,需要注意的是,如果2成立的话,那么每次4都需要执行。进制之间的转换:如234为5进制,那么转换成10进制是多少:2x5x5+3x5+4的值就是转换成的10进制。234e是16进制,转换成2进

19、制是多少:2x16x16x16+3x16x16+4x16+12的值就是转换成10进制的值。注意上面的规律。那么把十进制转换成r进制呢,其实很简单,就是把10进制数除以r,直到商是0的时候。然后取余数,余数倒序排列: 琐碎的运算符:自增:自减:和自增一样。三目运算符:最终的输出结果是1.逗号表达式:最终结果是6.上图中,逗号是个顺序点,即所有的副作用必须在下个语句前生效,其最后结果为1,j+2只是产生临时值,并没有把j+2的值赋个j。如果写成j+=2,那最后的值则变为5.For的嵌套使用举例:上例中输出的结果是9个哈哈,1个嘻嘻。在上图中,整个程序分成3个语句,输出的结果是3个嘿嘿,3个哈哈,1

20、个嘻嘻。其结果是:While(先付钱后吃饭)1:执行的顺序:2:与for的相互比较:用for来求1-100之和:用while实现1-100之和。只需要把for语句替换为:For和while是可以相互转换的,可以用下面的表达式来表示:While和for在逻辑上完全等价,但是for在逻辑上更强。更容易理解,更不容易出错。推荐多使用for。3:while举例:试数:通过上面的试数,应该能很快的理解回文数的算法。4:什么时候使用while,什么时候使用for:没法说,用多了就自然而然知道了Dowhile(先吃饭后付钱)一元二次方程:Switch的用法:电梯程序:Case是程序的入口,当进入程序后,程序

21、会从上往下执行,如果有break,那么会中断程序,如果没有,那么会一直执行。Break的用法:在多层循环中,Break只能终止他最近的循环。在多层switch中,break也是只能终止距离他最近的switch。Break只能用于循环和switch,不能用于if。如果用于if,必须要当循环中嵌套if的时候。Continue的用法:上图中,如果执行continue,那么C,D将不会被执行,会执行3.在上图中,如果执行了continue,那么后面的C,D将不再执行,而会去执行表达式。数组:-非重点 数组的使用:为什么需要数组1:为了解决大量同类型数据的存储和使用问题。2:用数组可以模拟现实世界。In

22、t a25:一维数组,可以当做一个线性结构。Int a86:可以当做一个平面,意思是8行6列。有48个元素。Int a345:可以当做一个三维 立体。Int a3456:可以当做一个四维空间。数组的分类一维数组怎样定义一维数组:为n个变量分配存储空间:数组内存空间是连续的。所有的变量类型必须相同:数组不可能第一个元素是整形,第二个元素是浮点型。所有变量所占用的字节必须相等。 例子:int 5数组不是学习重点的原因?数组一旦定义,其长度是死的。有关一维数组的操作 -都需要自己另外编程序实现而我们通常用第三方软件(工具)如数据库等方便直接地实现。对数组的操作:初始化 赋值 排序 求最大/小值 倒置

23、 查找 插入 删除初始化:上图中a5前面如果没有加上数据类型,那么这里的a5不是指一个数组,其中的5只的是下标。上图中,数组的5个元素不是用a来代表的,是用a0,a1a4来代表的,所以说数组名a代表的不是数组的5个元素,数组名代表的是数组的第一个元素的地址。赋值 把一个数组元素给全部倒过来:排序 求最大/小值 倒置 查找 插入 删除 二维数组:二维数组的初始化: 输出二维数组内容:多维数组:是否存在多维数组:不存在因为内存是线性一维的,在内存中是不分行不分列的。N维数组可以当做每个元素是n-1维数组的 一维数组。函数(第二个重点):为什么需要函数:避免了重复性操作。有利于程序的模块化。(自上而

24、下,逐步细化,大问题分解成小问题)用它作为参照,可以对比 JAVA 和C#面向对象的思想。C语言基本单位是函数,C#、C+和JAVA基本单位是类。什么叫做函数逻辑上:能够完成特定功能的独立的代码块。 物理上:能够接收数据【也可以不接收数据】,能够对接收的数据进行处理【也可以不对数据进行处理】,能够将数据处理的结果返【也可以没有返回值】。总结:函数是个工具,他是为了解决大量类似问题而设计的,函数可以当做黑匣子(内部原理不用管)。如何定义函数函数的返回值,函数的名字(函数的形参列表)函数的执行体函数定义的本质:详细描述函数之所以能够实现某个特定功能的具体方法。函数中的变量叫做形参;数组中的变量叫元

25、素。一旦函数执行完毕,其内部的形参所占空间就被收回。return表达式的含义:Return是终止被调函数,向主调函数返回表达式的值,如果表达式为空,则只终止函数,不向被主函数返回任何值。Break是用来终止(就近的)循环和switch语句。而return是用来终止被调函数的。函数返回值的类型,也称为函数的类型,因为如果函数名前的返回值类型和函数执行体中的return表达式中表达式的类型不同的话,则最终函数返回值的类型以函数名前的返回值类型为准。例:在上图中,函数的返回值以函数前的数值类型为准。函数的分类有参函数和无参函数。有返回值和无返回值。库函数和用户自定义函数。普通函数和主函数(main函

26、数)1:一个程序有且只有一个主函数。2:主函数可以调用普通函数,普通不能调用主函数。3:普通函数可以相互调用。4:主函数是程序的入口,也是函数的出口。5:值传递函数和地址传递函数。 判断一个数是否是素数:使用函数判断一个数是否是素数:函数和程序的调用应该注意的地方:函数的声明:当函数没有返回值时,那么规范的写法是要在函数中写明void的。在上图中,第一个void表示没有返回值,而第二个void表示不接收形参,也就是函数不接收数据。如果想把函数写在程序的后面,那么需要写函数声明:函数声明的含义是告诉编译器f()是个函数名。如果不加函数声明,那么编译器在编译到f的时候,不知道f是个什么,如果加了函

27、数声明,那么编译器编译到f的时候,就知道f是个函数。需要注意的是,调用语句需要放在定义语句的后面,也就是说,定义函数的语句要放在调用语句的前面。如果函数调用写在了函数定义的前面,则必须加函数前置声明,函数前置声明的作用是:1:告诉编译器即将可能出现的若干个字母代表的是一个函数。“打招呼”2:告诉编译器即将可能出现的若干个字母所代表的函数的形参和返回值的具体情况。3:函数声明必须是一个语句,也就是在函数声明后需加分号。4:对库函数的声明也就是系统函数。是通过#include来实现的。如stdio.h形参和实参要求:1:形参和实参个数是一一对应的。2:形参和实参的位置也是一一对应的。3:形参和实参

28、的数据类型需要相互兼容。 如何在软件开发中合理的设计函数来解决实际问题。 求1到某个数字之间的数是否是素数,并将他输出:合理设计函数1合理设计函数2:合理设计函数3:合理的设计函数4:合理设计函数5:常用的系统函数和如何通过书籍来学习函数: Turboc2.0实用大全机械工业出版社递归:(略)栈:相当于一个杯子(容器) 变量的作用域和存储方式: 全局变量和局部变量:局部变量:局部变量的使用范围只能在本函数内部使用。全部变量:全局变量和局部变量命名冲突的问题:在同一个范围之内不能定义两个一样的局部变量:在一个函数内部,如果定义的局部函数的名字和全局变量名一样时,局部变量会屏蔽掉全局变量:上例中最

29、终的输出结果是8,因为局部变量把全局变量给屏蔽掉了。指针:(C语言的灵魂)内存的存储是以一个字节为一个编号,也就是8位合在一起给一个编号,不是0,1就给编号。内存分为很多个单元,每个单元就会分配一个编号。地址:内存单元的一个编号。而指针和地址一个概念的。也就是说指针就是地址。普通变量:只能存放一个值。指针变量:同样是一个变量,但是指针变量存放其他变量的地址。*p代表的是p所指向的那个变量。在上图中*p和i是同一个东西,但是*p和p不是同一个东西。在上图中,int * p是一个声明,开头的int * 是他的数据类型。P是变量的名字。不能理解我定义了一个整形变量,这个整形变量的名字叫做*p。所谓i

30、nt *类型,实际就是存放int 变量地址的类型。*p代表的是以p的内容为地址的变量。解析:p的内容是一个地址,在上图中,p的内容就是i的地址,*p其指向的变量当然就是i变量了。指针和指针变量:指针就是地址,地址就是指针。地址就是内存单元的编号。指针变量:存放地址的变量。而指针只是一个值,这个值是内存单元的一个编号。指针变量才是一个变量,他里面才可以存放数据。指针和指针变量是两个不同的概念,但是需要注意的是,通常我们在叙述时会把指针变量简称为指针,实际他们含义并不一样。指针的重要性:指针的分类:指针的定义:地址:内存单元的编号,是一个从0开始的非负整数。范围:cpu对内存是通过控制、数据、地址

31、三条总线来进行控制的。控制:cup会先把内存中的数据读入,进行处理后,在返回给内存,然后内存在把数据写入硬盘。数据:用于数据的传输,不管是把内存中的数据发送给cpu,还是把cpu的数据写如内存条,都是由数据线来完成的,但是数据传输的方向则是由控制线来控制的。地址:地址线则是确定数据要写入内存中的那个单元。所谓的一个单元就是一个字节。一条地址总线能控制2的1次方,一般的机器有32个地址线,最终能够控制2的32个单元,而每个单元是八位,而最终我们的内存能够存储2的32次方*8位。则换算为G的话,最终大小为4G.那么地址总线的范围则是4G大。指针:指针就是地址,地址就是指针。 指针变量就是存放内存单

32、元编号的变量。 指针变量和指针是两个不同的概念。 指针的本质就是一个操作受限的非负整数。指针不能进行算术运算-相加 乘 除。但是能相减。如果两个指针变量指向的是同一块连续空间的不同存储单元,则这两个指针变量才可以相减。类似于同一个小区同一楼层六牌号相减表示两房间隔。这时才有现实意义。基本类型的指针:Int *p:p只能存放int类型的地址。P = & i:把i的地址赋给p。然后p就指向了i,*p就等于i。其实就是1:该语句保存了i的地址。2:p保存了i的地址,所以p指向i。3:p既然指向i,*p就是i。*p:表示以p的内容为地址的变量。*p:p是有指向的,p里面是个垃圾值,*p则是说以p的内容

33、为地址的变量。因为不知道p的值是多少,所以不知道*p到底代表的是那个变量。而*p = i,i=5,最终的结果就是把5赋给了一个所不知道的单元。 上图中,第一个error是数据类型不符合,不能相互转换。*q代表的是整形,因为*q代表的是以q的地址为内容的变量。而p是地址(int *)类型。第二个error同样有错,因为q没有赋值。经典指针程序-互换两个数字: 1:先用函数来互换:最终的输出结果没有互换,因为函数的a,b已经执行完成,分配给内存的空间已经释放了,所以最终a,b的值还是主函数a,b的值。互换的是形参的a,b。和主函数没有关系。在上图中,输出的值也是没有互换的,输出的同样是3,5,需要

34、注意的是,互换的只是p、q的内容,局部函数变化了,但是主函数是没有变化的。最终正确的程序:*号的三种含义:1:乘法2:定义指针变量。Int * p,定义了一个名字叫p的变量,int *表示p只能存放int变量的地址。3:指针运算符。该运算符是放在已经定义好的指针变量的前面。如果p是一个已经定义好的指针变量,则*P表示以p的内容为地址的变量。 注意理解形参,实参,和局部变量的关系。指针可以是函数返回一个以上的值:不使用指针的话,只能使用用return来返回一个值。如何通过被调函数修改主调函数普通变量的值指针和数组:指针和一维数组:(数组名 下标与指针关系 指针变量的运算)一维数组名:一维数组名是

35、个指针常量,他存放的是一维数组第一个元素的地址。常量是不能被改变的,也就是说,一维数组名是不能被改变的。数组名a存放的是一维数组第一个元素的地址,也就是a = &a。printf(“%#Xn”,&a0); = printf(“%#Xn”,a);指针和二维数组:下标和指针的关系:如果p是个指针变量,则pi永远等价于*(p+i)确定一个一维数组需要几个参数,【如果一个函数要处理一个一维数组,则形参需要接收该数组的哪些信息。】确定一个一维数组需要两个参数,1:数组名,从数组的名称就可以知道数组的第一个值,因为一维数组的名称就是数组的第一个元素的地址。2:是数组的个数。来计算该数组有多少个值。区别于

36、字符串(只需要一个参数首地址)因为字符串默认其后面都有一个“/0”作为结束标志。而数组并没有相关约定。在上图中,a是个指针变量,所以上面局部函数f的pArr则要定义成指针函数才可以,而len则是int类型。代表接收的是整型的数字。 在上图中因为数组a的名称代表的是a的第一个元素的地址,所以在函数f中所定义的指针变量pArr和a是相同的,因为a也是指针类型。也就是说pArr=a=a0,pArr1=a1=*(pArr+1)=*(a+1),pArr2=a2=*(pArr+2) =*(a+2).所以在f函数中pArr3=a3,所以第二个printf输出的结果是88.总结:pArri = ai = *(

37、pArr+i) = *(a+i)在没有学习指针时,可将a3认为是数组中第4个元素,但现在应该对其内部原理有更深刻认识。这里下标也当成指针了,从首元素开始向后移动3个,即指向第4个元素。在上图中因为数组a的名称代表的是a的第一个元素的地址,所以在函数f中所定义的指针变量pArr和a是相同的,因为a也是指针变量类型。也就是说pArr=a=a0,pArr1=a1=*(pArr+1)=*(a+1),pArr2=a2=*(pArr+2) =*(a+2).通过上图,我们知道,我们在f函数中修改数组的值,相当于修改主函数中相对应的值。何谓变量地址 / 一个指针占几个字节Sizeof(变量名/数据类型) 其返

38、回值就是该变量或数据类型所占字节数。一个指针变量无论其指向变量占几个字节,其本身所占大小都是4字节。*p具体指向几个字节,要靠前面类型确定,如果为int则为4字节,如果double则占8字节。CPU 与 内存 交互时 有32根线,每根线只能是1或0两个状态,所有总共有232个状态。1 个状态 对应 一个单元。如全为0 全为1 等。内存中第一个单元,即32根线状态全为0。0000 0000 0000 0000 0000 0000 0000 0000 其大小为4字节所有每个地址(硬件所能访问)的用4个字节保存(而不是一 位bit)一个变量的地址用该变量首字节的地址表示。这也就是为什么指针变量始终只

39、占4字节的原因。接下来是:138课 动态分配内存(很重要)专题:138讲动态内存分配 (所有高级语言,没有C里深刻,对JAVA、C#理解有益)传统数组的缺点:1.数组长度必须事先指定,而且只能是常整数,不能是变量例子int a5; /必须事先指定,而且只能是常整数 int len = 5; int alen;/error2.传统形式定义的数组,该数组的内存程序员无法手动释放数组一旦定义,系统为数组分配的内存空间就会一直存在,除非数组所在的函数运行终止。在一个函数运行期间,系统为该函数中的数组分配的空间会一直存在。直到该函数运行完毕时,数组的空间才会被系统自动释放(不是清零)。例子:void f

40、(void) int a5=1,2,3,4,5;./数组a 占20个字节的内存空间,程序员无法手动编程释放它,数组a只能在f()函数结束被系统释放3. 数组的长度一旦定义,数组长度就不能再更改。数组的长度不能在函数运行的过程中动态的扩充或缩小4. 传统方式定义的数组不能跨函数使用A函数定义的数组,只有在A函数运行期间才可以被其他函数使用,但A函数运行完毕后,A函数中的数组将无法在被其他函数使用。#includevoid g(int * pArr, int len) pArr2 = 88; /parr2=a2 等价于 void f(void) int a5 = 1,2,3,4,5; /数组a 只

41、在f()执行时有效 g(a,5);printf(%dn, a2);int main(void) f(); / 结果: 88/printf(a0 = %dn, a0); / error return 0;为什么需要动态分配内存很好的解决的了传统数组的4个缺陷动态内存分配举例_动态数组的构造 难点/*2011-05-01malloc是memory(内存) allocate(分配)的缩写动态内存空间是怎么造出来的?*/#include #include int main(void)int i = 5; /分配了4个字节,静态分配int * p = (int *)malloc(100);/*1. 要使

42、用malloc函数,必须要添加malloc.h头文件2. malloc函数只有一个形参,并且形参是整型3. 100表示请求系统为本程序分配100个字节4. malloc函数只能返回第一个字节的地址,但此时并不能确定该变量的类型,只有将这个地址被强制类型转化成存放整型变量的地址,这时才传达出指向整型变量的信息。5. 系统总共分配了104个字节的内存空间,p变量本身占4个字节(静态分配),p所指向的内存占100个字节(动态分配) 若为int 则可存25个,若为char则可存100个变量。6. p本身所占的内存是静态分配的,p所指向的内存是动态分配的*/free(p);/free(p)表示把p说指向

43、的内存空间给释放掉,/p本身的内存不能释放,只有main函数终止时,由系统自动释放*p = 5; /*p代表的就是一个这int变量,*p这个整型变量的内存分配方式和int i =5;不同。/*p是内存是动态分配的, int i是静态的。printf(同志们好!n);return 0;-/*2011-05-01目的: malloc使用_2*/#include #include void f(int * q) /q是p的拷贝或副本 q等价于p *q等价于*p *q=200则*p=200/*p = 200; /error f()没有p变量,p是在main()函数定义的/ q = 200; /erro

44、r q是指针变量(地址),200是整数int *q = 200; /OK!类型一致/ * *q 语法错误 !*q整型变量, 只有指针变量前可以加*/free(q);/把q指向的内存释放掉int main(void)int * p = (int *)malloc(sizeof(int);/sizeof(int)=4;*p = 10;printf(%dn, *p); /10f(p);printf(%dn, *p); /200/ f()函数中 free(q)作用后,则输出 -572662307(垃圾值)return 0;/*2011-05-02目的:动态一维数组示例realloc(pArr, 100

45、)/扩充动态内存空间 (原来50变100;原来150变100)/保留原来动态内存中未被截取的内容*/#include #include int main(void) /int a5; /系统静态地分配20个字节的空间给数组aint len;int *pArr;printf(请输入你要存放的元素个数: );scanf (%d, &len);/5pArr = (int *)malloc(4*len);/pArr指向这20个字节动态空间的前4个字节/*动态的构造了一个一维数组,该数组的长度len, 数组名是pArr, 数组元素类型是int类似与int pArrlen; len可以根据需要变化*/对一

46、维数组进行操作,如:对动态一维数组进行赋值for (int i=0; ilen; +i)scanf(%d, &pArri); printf(动态数组元素为: n);/对一维数组进行输出for(i=0; ilen; +i)printf(%dn, pArri);free(pArr);/动态空间被释放printf(%dn, *(pArr+1); /动态空间被释放,原来动态数组数元素内容为垃圾值-572662307return 0;/*-在VC+6.0输出结果:请输入你要存放的元素个数:44 6 8 10动态数组元素为:46810*/使用动态数组的优点:1.动态数组长度不需要事先给定;2.内存空间可以

47、手动释放;3.在程序运行中,动态内存空间大小可以通过realloc函数手动扩充或缩小静态内存和动态内存的比较静态内存是由系统自动分配,有系统自动释放静态内存是在栈分配的动态内存是由程序员手动分配、手动释放动态内存是在堆分配的 /*2011-05-02目的: 多级指针 - 自己画几个示意图 就会豁然开朗。/#include int main(void) int i = 10;/ iint * p = &i; / 最终 *p就是 i;int* *q = &p; / q 只能存放 int *类型的地址 即p 的地址&pint* *r = &q; / r 只能存放 int *类型的地址 即q 的地址&

48、q/r = &p; /error! 因为r是int*类型,只能存放int *类型变量的地址printf(i = %dn, *r); *r = q; *r = *q =p *r = *q = *p = i;printf(i = %dn, *q); *q = p ; *q = *p = i printf(i = %dn, *p); *p = i;printf(i = %dn, i);return 0;/*-在VC+6.0输出结果:i = 10i = 10i = 10i = 10*/#include /多级指针在函数中的应用void f(int * q)*q = 100;/*q就是pvoid g()

49、int i = 10;int * p = &i;printf(i = %d *p = %dn, i, *p);f(&p); /p是int *类型&p就是int * 类型printf(i = %d *p = %dn, i, *p); int main(void) g();return 0;/*-在VC+6.0输出结果:i = 10 *p = 10i = 100 *p = 100*/ #include #include void f(int * q) /q是p的拷贝副本*q = 1;void g(int *r)*r = 2;void h(int *s)*s = 3;void i(int *t)*t

50、 = 4;/要想修改函数变量的值,只能发送该变量的地址,修改一个以上的值,必须用指针int main(void) int *p = (int *)malloc(4);printf(*p = %dn, *p);/垃圾值f(p); /调用的是指针printf(*p = %dn, *p);/1 g(&p);/调用的是指针变量的地址printf(*p = %dn, *p);/2/h(&(&p);/ error C2102: & requires l-valueint *pp = &p; /pp是存放p地址的指针, int * 整型指针的指针类型h(&pp); /调用的是存放p指针的指针的地址int *

51、整型指针的指针的指针类型printf(*p = %dn, *p);/3int *ppp = &pp;i(&ppp);/调用的是一个三级指针的指针的地址,int * 整型四级指针printf(*p = %dn, *p);/4return 0;跨函数使用内存的问题难点/*2011-05-02目的:跨函数使用内存 函数内的静态空间,不能被其他函数调用访问*/#include void f(int *q) /理解为 int* *qint i =5;/*q等价于p*p和*q都不等价于p/*q = i;/error *q等价于p 推出 p=i; 错!*q = &i;/*q = *p = i;int mai

52、n(void) int *p;f(&p);printf(%dn, *p);return 0; /*结果:5本语句语法没有问题,但逻辑上有问题 内存越界:程序访问了一个不该被访问的内存函数内的静态空间,不能被其他函数调用访问函数中的内存空间,随函数终止而被释放。内存空间释放后的内容不属于其他函数,其他函数无权限访问。但释放后的内存空间的地址是可以被其他函数读取的。但指针变量可以存贮任何函数中静态内存空间的地址,p都能存垃圾,p想存谁存谁。只是它此时已经没有权限读取(访问)i这个地址的数据了,出错。*/*2011-05-02目的:动态内存可以跨函数访问程序运行在栈顶进行静态空间是在栈里面分配的,函

53、数终止本质叫做出栈,所以静态空间随着函数终止而释放,动态空间是在堆里面分配的,与栈无关,与函数终止无关,不随着函数终止而释放。堆和栈相关深入知识就需要数据结构和操作系统两门课学习,而这两门课难度大,理论性强,短期内收不到立竿见影的成效,属于内功心法,因此大多培训班已经取消了学习。可以用free()释放*/#include #include void f(int * q)/*q等价p 已经声明了q的类型为int *q = (int *)malloc(sizeof(int);/sizeof(整数类型)/*不要用4,因为c语言只规定short int字节数 小于 int字节数 小于 long int

54、字节数,没有规定明确的字节数,无统一硬性规定。 不同软件系统可能出现不同,统一用sizeof(int)来获取实际值int * p;在p声明的情况下,构造动态空间也可以写成 p = (int *)malloc(sizeof(int);*/ *q等价p, 等价于 p = (int *)malloc(sizeof(int);/ q = 5;/error! q指针/ *q = 5;/error! p = 5 *q = 5;/OK! 等价于 *p = 5int main(void) int * p;f(&p);/只有调用变量的地址,才能改变变量的值printf(%dn, *p); /f函数中,没有fre

55、e(q);所以动态空间仍然保留,动态空间中的内容可以被访问return 0;/*-在VC+6.0输出结果:5*/枚举什么是枚举把一个事物所以可能的取值一一列举出来/*日期:2011-05-04目的:枚举*/#include /自定义了一个数据类型,并没有定义变量,该数据类型的名字 enum WeekDayenum WeekDay/MonDay, TuesDay, WednesDay, ThursDay, FriDay, SaturdDay, Sunday MonDay=10, TuesDay, WednesDay, ThursDay, FriDay, SaturdDay, Sunday;/分号int main(void)/int day;/day定义成int类型范围太大不合适,day的取值只可能有7个(0-6),浪费空间enum WeekDay day = FriDay; /初始化一个enum WeekDay 类型变量 dayprintf(%dn, day);return 0;

展开阅读全文
温馨提示:
1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
2: 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
3.本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
关于我们 - 网站声明 - 网站地图 - 资源地图 - 友情链接 - 网站客服 - 联系我们

copyright@ 2023-2025  zhuangpeitu.com 装配图网版权所有   联系电话:18123376007

备案号:ICP2024067431-1 川公网安备51140202000466号


本站为文档C2C交易模式,即用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。装配图网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知装配图网,我们立即给予删除!