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

上传人:彩*** 文档编号:76146632 上传时间:2022-04-17 格式:DOC 页数:42 大小:551KB
收藏 版权申诉 举报 下载
郝斌C语言详细笔记附源码_第1页
第1页 / 共42页
郝斌C语言详细笔记附源码_第2页
第2页 / 共42页
郝斌C语言详细笔记附源码_第3页
第3页 / 共42页
资源描述:

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

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

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

3、长: c 语言是面向过程的语言,面向过程的语言的特点就是在开发大项目的时候,很容易崩溃,好比盖大楼, C 语言还要造大量的砖块、钢筋等结构原材料,而 C+C#JAVA则进行了一定的继承封装等操作,相当于原材料直接给你,你只需要用它盖楼即可。现在市场上的语言分三块C/c+: 单纯的学习 c 是什么都做不了的。JavaC#可移植性不强:这是针对java 来说的,因为java 的可移植性太强了,所以就感觉说c 的可移植性不强。金山公司最主要是靠wps 办公软件来发展的。Wps是 c 语言开发的,其安装包比Office少了 10 多倍。三大操作系统 :windows, unix ,linuxWindo

4、ws内核是 c 语言写的,而外壳是c+写的。 Java 永远不可能写操作系统。因为java 运行速度太慢了。而 linux 和 unix 都是纯 c 写的。操作系统控制了硬件,如果说操作系统的运行速度慢,那么当我们在运行软件的时候,运行速度会更慢。为什么使用 c 语言写操作系统 呢,首先是因为 c 的运行速度快,然后是因为 c 可以直接控制硬件,而其他语言不可以。 没有指针的语言是不能直接访问硬件的 。C语言的应用领域 :驱动一般是用c 和汇编来写的。数据库一般是用c 和 c+来写的C语言的重要性 :虽然应用场合相对较窄,但贴近系统内核,较底层。病毒最基本的是要感染系统,数据结构, c,c+这

5、三门语言是必须要学习的。牛人牛语:怎样学习 c 语言要将编程当成一项事业来经营,而不是糊口的工具。多思考,多上机。不能光看,光听,而要排错,调试。在犯错误中成长。参考资料王爽写的 c+也很不错学习的目标 :掌握简单的算法 - 解决问题的方法和步骤。熟悉语法规则。能看懂程序并调试程序。C语言的 关键字 :C语言程序的 格式:一定要养成良好的习惯:代码规范边写边保存,括号成对出现,应用空格软件操作:新建保存关闭(关闭空间).cpp 是原始文件,可单独拷贝到其它电脑。第二讲:( 14)c 语言编程 必备知识1. Cpu,内存条,硬盘,显卡,主板,显示器之间关系。Cpu不能直接处理硬盘上的数据,必须要

6、先调入内存2. Helloword 程序是如何运行起来的。3. 什么是数据类型数据类型 - 数据的分类,对编程而言,首要考虑问题是数据的输入和存储。可以分为A:基本数据类型:整型整型 int-4 字节一字节 byte=8 位 bit短整型 shortint-2长整型 longint-8浮点型单精度浮点数 float :存储范围小 -4 双精度浮点数 double :存储范围大 -8Float和 Double 都不能保证将小数完全准确保存。字符 char :c 语言中是没有字符串string-1(区别于 JAVA、C#中有 string且 C#中 char 为 2 字节)B:复合类型:就是把基本

7、类型拼凑在一起结构体枚举 - 实用共用体基本淘汰4什么是变量变量的本质 是内存中一段存储空间。IntI;i=5;I是变量,程序向系统申请了一个内存单元,在程序运行中, i 的值可以改变,但程序结束后,其所占的空间不是释放,而是被系统收回权限。5 Cpu,内存条, vc+,操作系统之间的关系。6 变量为什么必须初始(即赋值)1. 软件在运行前需要向操作系统申请存储空间,在内存空间足够空闲时,操作系统将分配一段内存空间并将该外存中软件拷贝一份存入该内存空间中,并启动该软件运行。2. 在软件运行期间,该软件所占内存空间不再分配给其他软件。3. 当该软件运行完毕后, 操作系统将回收该内存空间 (注意:

8、操作系统并不清空该内存空间遗留下来的数据) ,以便再次分配给其他软件使用。操作系统 一门课中系统分配表中会讲到,用 1 标记表示内在是被占用的,用0 标记表示是空闲的。综上所述,一个软件所分配到的空间中极可能存在着以前其他软件使用过后的残留数据,这些数据被称之为 垃圾数据,所以通常情况下我们为一个变量,为一个数组,分配好存储空间之前都要对该内存空间初始化。7 如何定义变量数据类型变量名称 =赋予的值;等价于数据类型变量名;变量名 =要赋予的值;举例子:inti=3; 等价于 inti ;i=3 ; Inti ,j ;等价于 inti ; intj ;Inti,j=3 等价于 inti;intj

9、;j=3;IntI=3 , j=5 ;等价于 inti;intj;I=3 ; j=5 ;8 什么是进制 逢几进一我们规定八进制前面加 0(零),十六进制前面加 0x。常用计数制对照表:Printf 的基本用法:9 常量在 c 中是如何表示的当个字符使用单引号括起来,多个字符串使用双引号括起来(指针、数组)。在 c 中,默认是 double 类型的。在后面加 F 表示当做 float来处理,否则会有警告提示- 丢失部分字节。10常量以什么样的二进制代码存储在计算机中?编码:整数是以补码的形式转换为二进制代码存储在计算机浮点数是以 ieee754 标准转换为二进制代码存储字符本质实际是与整数的存储

10、方式相同,ASII 码标准。第三次课:代码规范化可以参考林锐高质量c/c+ 编程代码的规范化非常的重要,是学习一门编程语言的基础,代码可以允许错误,但不能不规范。例如:成对敲括号 ()加空格于运算符和数字之间I=1+2;加缩进分清上下级地位。换行 - 进行功能区域分隔or 括号单独成一行。代码规范化的好处1:整齐,别人和自己都容易看懂。2:代码规范了,代码不容易出错。3:一般的程序可以分为三块:a: 定义变量b:对变量进行操作c: 输出值什么是字节存储数据的单位,并且是 硬件所能访问的最小单位 。内存中存储的最小单位是位bit(0或 1) ,但是硬件控制的时候不能精确到位,只能精确到字节(8

11、位),是通过地址总线来控制的,而精确到位是通过软件来控制的,叫做位运算符来精确到位的。1 字节 =8 位 1K=1024字节1M=1024K1G=1024 M1T=1024 G2G的内存条 的总空间: 2*1024*1024*1024*8=4*10 32不同类型数据之间相互赋值的问题不同数据类型之间最好不要相互转换。如果需要明白这个知识点,那么需要明白补码 。什么是 ASCII 码以 char 定义变量的时候,只能使用单引号括起一个字符才是正确的。在上图中注释的最后一样是重复定义了ch 的值,是错误的,而下面的 ch=c是指把 c 赋值给 ch,是正确的。上图中输出的值是98( 将字符以整数

12、%d的形式输出 )Ascll码规定了 ch 是以哪个值去保存,ascii码不是一个值,而是一种规定,规定了不同的字符是以哪个整数值去表示。其它规定还有 GB2312UTF-8等。字符本质上与整数的存储方式相同【字符的存储】基本的输入和输出函数的用法:第三次课Printf()将变量的内容输出到显示器上。四种用法输什么是输出控制符,什么是非输出控制符输出控制符包含如下:Printf为什么需要输出控制符: 01 组成的代码可以表示数据也可以表示指令。必须要有输出控制符告诉他怎么去解读。如果 01 组成的代码表示的是数据的话,那么同样的01 代码组合以不同的格式输出就会有不同的输出结果,所以必须要有输

13、出控制符。在上图中, intx=47 ,如果前面加0(零)048 表示的是八进制,如果前面加 0x(零 x)0X47则表示的是十六进制,而在输出的时候,则是 o( 字母 o) 表示八进制 , ox(字母 o, x)表示十六进制。非输出控制符 :非输出控制符在输出的时候会原样输出。Scanf ()通过键盘将数据输入到变量中有两种用法:示例:非输入控制符:在输入的时候也会原样输入。但是强烈建议:在使用scanf 的时候,不使用非输入控制符。给多个变量赋值:需要记住,非控制符需要原样输入。如何使用 scanf 编写出高质量代码运算符:算术运算符:加( +),减()乘( * )除( / )取余( %)

14、关系运算符:,=,关系 逻辑 赋值 。取余的结果的正负只和被除数有关。第四节流程控制(第一个重点):1 什么是流程控制程序代码执行的顺序。2 流程控制的 分类顺序执行选择执行定义:某些代码可能执行,可能不执行,有选择的执行某些代码。分类: ifIf最简单的用法:如果想控制多个语句的执行或者不执行,那么需要使用 括起来。else 的用法:if elseifelse的用法:C错误的 if elseifelse语句:在上图中,当执行到哈哈那句时,下面的else 将会被算作另外一个语句来执行,而在我们的c 语言中,没有以else 开头的语句。所以会出错。If实例:If常见的问题:变量的替换 :求三个数

15、字的大小:C语言常见误区 :纸老虎素数:只能被1 和自己整除的数,如1,5,9 等。回文数:正着写和倒着写一样的数。如1221,121 ,等编程实现求一个十进制数字的二进制形式:求一个数字的每位是奇数的数字取出来组合形成的新数字。求一个数字到过来的数字。1:如果不懂,那么就看答案。看懂答案在敲。没错误了,在尝试改。如何看懂一个程序 :1. 流程:2. 每个语句的功能:3. 试数:对一些小算法的程序 :1. 尝试自己编程结局。2. 解决不了,看答案。3. 关键是把答案看懂。4. 看懂之后尝试自己修改程序, 且知道修改之后程序的不同输出结果的含义。5. 照着答案去敲6. 调试错误7. 不看答案,自

16、己独立把程序编出8. 如果程序实在是彻底无法了解,就把他背会。空语句的问题:在上图中,最终的结果会是AAAA,BBBB,程序也不会报错,为什么呢,因为在程序执行的时候,会在;哪里认为是一个空语句。也就是说,如果if成立,那么执行空语句。If常见错误解析(重点)上面这个程序是错误的,为什么呢,在该程序中,总的有 4 个语句,而在以 else 开头的那个语句中是有错误的,因为在 c 语言中是没有以 else 开头的这种语法。在上面这个程序中,最终的值是AAAA,虽说后面的 31 也满足条件,但是当 32 满足条件后,该if 语句就会终止,后面的语句是不会在执行的。既然 7 行要写表达式,就要写if

17、 。循环的定义、分类。定义:某些代码会被重复执行。分类: forwhiledo while在上图中,先执行 1,在执行 2,2 如果成立,标志着循环成立,那么在执行 4,最后在执行 3,3 执行完后代表一次循环完成,然后在执行 2. 以此类推。 1 永远只执行一次。+I 等价于 i+1求 1-10 的所有奇数的和:求 1-12 之间的所有能被3 整除的数字之和:For 所控制的语句:在上图中, for 默认只能控制一个语句,但是如果要控制多个语句时候,那么需要使用 把语句括起来。求 1+1/2+1/3 .1/100 的和在上图中,重点是强制数据类型转换也就是 (float)(i)那句:如果把

18、print那句换为下面这句会怎么样呢:也是错的,为什么呢,因为i 是整型, 1 也是整型,所以不管你怎么转换也是整型啊,如果想要这样写的话,那么我们需要把 1 改成也可以的。也就是:试数详细步骤举例:浮点数存取 :求 1-100 之间所有奇数的和:求 1-100 之间的奇数的个数:求 1-100 之间奇数的平均值:求 1-100 之间的奇数之和,在求 1-100 之间的偶数之和:多个 for 循环的嵌套 使用:整体是两个语句。上图中,先执行 1,在执行 2,如果 2 成立,执行 4,在执行5,如果 5 成立执行 A, 在执行 6,在执行 5,如果 5 不成立,意味着里面的循环结束,然后执行3,

19、在执行 2,如果 2 成立又执行 4,在执行 5,如果 5 成立在执行 6,在执行 5,如果 5 不成立,在执行 3,在执行 2,如果 2 不成立,意味着本次循环结束,在执行 B,在上图中,需要注意的是,如果 2 成立的话,那么每次 4 都需要执行。进制之间的转换 :如 234 为 5 进制,那么转换成 10 进制是多少:2x5x5+3x5+4 的值就是转换成的10 进制。234e 是 16 进制,转换成2 进制是多少:2x16x16x16+3x16x16+4x16+12 的值就是转换成10 进制的值。注意上面的规律。那么把十进制转换成 r 进制呢,其实很简单,就是把 10 进制数除以 r ,

20、直到商是 0 的时候。然后取余数,余数倒序排列:琐碎的运算符:自增:自减:和自增一样。三目运算符:最终的输出结果是1.逗号表达式 :最终结果是 6.上图中,逗号是个顺序点,即所有的副作用必须在下个语句前生效,其最后结果为 1,j+2 只是产生临时值,并没有把 j+2 的值赋个 j 。如果写成 j+=2 ,那最后的值则变为 5.For 的嵌套使用举例:上例中输出的结果是9 个哈哈, 1 个嘻嘻。在上图中,整个程序分成3 个语句,输出的结果是3 个嘿嘿, 3个哈哈, 1 个嘻嘻。其结果是:While (先付钱后吃饭)1:执行的顺序:2:与 for 的相互比较:用 for 来求 1-100 之和:用

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

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

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

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

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

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

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

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

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

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

31、我定义了一个整形变量,这个整形变量的名字叫做 *p 。所谓 int* 类型,实际就是存放 int 变量地址的类型。*p 代表的是以 p 的内容为地址的变量。解析: p 的内容是一个地址,在上图中, p 的内容就是 i 的地址, *p 其指向的变量当然就是 i 变量了。指针和指针变量:指针就是地址,地址就是指针。地址就是内存单元的编号。指针变量:存放地址的变量。而指针只是一个值,这个值是内存单元的一个编号。指针变量才是一个变量,他里面才可以存放数据。指针和指针变量是两个不同的概念,但是需要注意的是,通常我们在叙述时会把指针变量简称为指针,实际他们含义并不一样。指针的重要性:指针的分类 :指针的定

32、义: 地址:内存单元的编号,是一个从 0 开始的非负整数 。范围: cpu 对内存是通过 控制、数据、地址三条总线 来进行控制的。控制: cup 会先把内存中的数据读入,进行处理后,在返回给内存,然后内存在把数据写入硬盘。数据:用于数据的传输,不管是把内存中的数据发送给 cpu,还是把 cpu 的数据写如内存条,都是由数据线来完成的,但是数据传输的方向则是由控制线来控制的。地址:地址线 则是确定数据要写入内存中的那个单元。所谓的一个单元就是一个字节。一条地址总线能控制 2 的 1 次方,一般的机器有 32 个地址线,最终能够控制 2 的 32 个单元,而每个单元是八位,而最终我们的内存能够存储

33、 2 的 32 次方 *8 位。则换算为 G的话,最终大小为 4G.那么地址总线的范围则是 4G 大。指针:指针就是地址,地址就是指针。指针变量就是存放内存单元编号的变量。指针变量和指针是两个不同的概念。指针的本质就是一个操作受限的非负整数。指针不能进行算术运算- 相加乘除。但是能相减。如果两个指针变量指向的是同一块连续空间的不同存储单元,则这两个指针变量才可以相减。类似于同一个小区同一楼层六牌号相减表示两房间隔。这时才有现实意义。基本类型的指针:Int*p :p 只能存放 int类型的地址。P=&i:把 i 的地址赋给 p。然后 p 就指向了 i ,*p 就等于 i 。其实就是1:该语句保存

34、了i 的地址。2:p 保存了 i 的地址,所以p 指向 i 。3:p 既然指向 i ,*p 就是 i 。*p :表示以 p 的内容为地址的变量。*p :p 是有指向的, p 里面是个垃圾值, *p 则是说以 p 的内容为地址的变量。因为不知道 p 的值是多少,所以不知道 *p 到底代表的是那个变量。而 *p=i ,i=5 ,最终的结果就是把 5 赋给了一个所不知道的单元。上图中,第一个error是数据类型不符合,不能相互转换。 *q 代表的是整形,因为 *q 代表的是以 q 的地址为内容的变量。而 p 是地址( int* )类型。第二个 error同样有错,因为q 没有赋值。经典指针程序 -

35、互换两个数字 :1:先用函数来互换:最终的输出结果没有互换,因为函数的a,b 已经执行完成,分配给内存的空间已经释放了,所以最终a,b的值还是主函数a,b 的值。互换的是形参的a,b。和主函数没有关系。在上图中,输出的值也是没有互换的,输出的同样是3,5 ,需要注意的是,互换的只是p、q 的内容,局部函数变化了,但是主函数是没有变化的。最终正确的程序:* 号的三种含义 :1:乘法2:定义指针变量。 Int*p ,定义了一个名字叫 p 的变量, int* 表示 p 只能存放 int 变量的地址。3:指针运算符。该运算符是放在已经定义好的指针变量的前面。如果p 是一个已经定义好的指针变量,则*P

36、表示以 p 的内容为地址的变量。注意理解形参,实参,和局部变量的关系。指针可以是函数返回一个以上的值:不使用指针的话,只能使用用return来返回一个值。如何通过被调函数修改主调函数普通变量的值指针和数组 :指针和一维数组:(数组名下标与指针关系指针变量的运算) 一维数组名 :一维数组名是个指针常量,他存放的是一维数组第一个元素的地址。常量是不能被改变的,也就是说,一维数组名是不能被改变的。数组名 a 存放的是一维数组第一个元素的 地址,也就是a=&a。printf(“ %#Xn” ,&a0);=printf(“ %#Xn”,a);指针和二维数组:下标和指针的关系 : 如果 p 是个指针变量,

37、则pi永远等价于 *(p+i)确定一个一维数组需要几个参数,【如果一个函数要处理一个一维数组,则形参需要接收该数组的哪些信息。】确定一个一维数组需要两个参数,1:数组名,从数组的名称就可以知道数组的第一个值,因为一维数组的名称就是数组的第一个元素的地址。2:是数组的个数。来计算该数组有多少个值。区别于字符串(只需要一个参数首地址)因为字符串默认其后面都有一个“/0 ”作为结束标志。而数组并没有相关约定。在上图中, a 是个指针变量,所以上面局部函数f 的 pArr 则要定义成指针函数才可以,而len 则是 int类型。代表接收的是整型的数字。在上图中因为数组a 的名称代表的是a 的第一个元素的

38、地址,所以在函数 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=*(pArr+i)=*(a+i)在没有学习指针时,可将 a3 认为是数组中第 4 个元素,但现在应该对其内部原理有更深刻认识。这里下标也当成指针了,从首元素开始向后移动 3 个,即指向第 4 个元素。在上图中因为数组 a 的名称代表的是a 的第一个元素的地址,所以在函

39、数 f 中所定义的指针变量pArr 和 a 是相同的,因为a 也是指针变量类型。也就是说pArr=a=a0 ,pArr1=a1=*(pArr+1)=*(a+1),pArr2=a2=*(pArr+2)=*(a+2).通过上图,我们知道,我们在f 函数中修改数组的值,相当于修改主函数中相对应的值。何谓变量地址 / 一个指针占几个字节Sizeof( 变量名 / 数据类型 ) 其返回值就是该变量或数据类型所占字节数。一个指针变量无论其指向变量占几个字节,其本身所占大小都是4字节。*p 具体指向几个字节,要靠前面类型确定,如果为字节,如果 double 则占 8 字节。CPU与内存交互时有32 根线,每

40、根线只能是1 或int则为 40 两个状态,所有总共有232 个状态。1 个状态对应一个单元。如全为0 全为1 等。内存中第一个单元,即32 根线状态全为0。00000000000000000000000000000000其大小为 4 字节所有每个地址(硬件所能访问)的用4 个字节保存(而不是一位 bit )一个变量的地址用该变量首字节的地址表示。这也就是为什么指针变量始终只占 4 字节的原因。接下来是: 138 课动态分配内存(很重要)专题: 138讲动态内存分配 ( 所有高级语言,没有 C里深刻,对 JAVA、C#理解有益 )传统数组的缺点:1. 数组长度必须事先指定,而且只能是常整数 ,

41、不能是变量例子inta5;统形式定义的数组,该数组的内存程序员无法手动释放数组一旦定义,系统为数组分配的内存空间就会一直存在,除非数组所在的函数运行终止。在一个函数运行期间,系统为该函数中的数组分配的空间会一直存在。直到该函数运行完毕时,数组的空间才会被系统自动释放(不是清零)。例子: voidf(void)inta5=1,2,3,4,5;.组的长度一旦定义,数组长度就不能再更改。数组的长度不能在函数运行的过程中动态的扩充或缩小4. 传统方式定义的数组不能跨函数使用A函数定义的数组,只有在 A函数运行期间才可以被其他函数使用,但A函数运行完毕后, A函数中的数组将无法在被其他函数使用。#inc

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

43、的*/free(p);2011-05-012011-05-02 态数组长度不需要事先给定;2. 内存空间可以手动释放;3. 在程序运行中,动态内存空间大小可以通过 realloc 函数手动扩充或缩小静态内存和动态内存的比较静态内存是由系统自动分配,有系统自动释放静态内存是在栈分配的动态内存是由程序员手动分配、手动释放动态内存是在堆分配的/*2011-05-02目的:多级指针 - 自己画几个示意图就会豁然开朗。/#includeintmain(void)2011-05-022011-05-021214 17 32c 4G截留inti=10;2011-05-042011-05-0432c后者类型所

44、占的字节数。例如: int 类型转化为 char 则高 3位字节被截取。只保留最后一位字节。结构体(非重点)为什么需要结构体为了表示一些复杂的事物,而普通的基本类型无法满足实际要求。什么叫结构体把一些基本类型数据组合在一起形成的一个新的复合数据类型。如何定义结构体3种方式:员名2指针变量名 - 成员名(更常用)它会在计算机内部转化成(* 指针变量名 ). 成员名的方式来执行。所以两者是等价的。例子:StructStudentIntage;Floatscore;Charsex;Intmain(void)StructStudentst=80,66.6f,F;的方式来执行 , 没有为什么,这就是 -

45、 的含义,这也是一种硬性规定。2所以 pst-age 等价于 (*pst).age也等价于3pst- 的含义: pst 所指向的那个结构体变量中的age这个成员。结构体变量的大小略大于其内部成员类型所占字节数之和。试:sizeof(struct)若想通过函数对主函数结构体变量进行修改,则主函数必须发送地址,外函数定义指针结构体变量,通过外函数内部语句完成对变量的修改。而仅想输出、读取操作,则不用传地址,定义指针过程。例:/*2009年11月 24日9:17:43通过函数完成对结构体变量的输入和输出*/#include#includestructStudentintage;charsex;cha

46、rname100;ge=10;ame=张三丰 ; 都是 error ,提示错误信息:cannotconvertfromchar5tochar100 strcpy(pstu-name, 张三丰 );2009 年11月24日 ge=10; strcpy(pstu-name, 张三 );pstu-sex=F;结构体变量的运算不能加减乘除操作,只能相互赋值。例如: structStudentIntage;Charsex;Char100;StructStudentstr1,str2;Str1=str2/str2=str1;都是正确的。举例:动态构造存放学生信息的结构体数组#include#include

47、ge);printf(name=);scanf(%s,pArri.name);ame不能改成 &pArri.nameprintf(score=);scanf(%f,&pArri.score);corepArrj+1.score)ge);printf(name=%sn,pArri.name);printf(score=%fn,pArri.score);printf(n);return0;总结:对于一个人事管理或图书管理项目,分析流程:第一步;存储第二步:操作第三步:输出前两个过程最难、最核心是“数据结构”研究的重点,一般都屏蔽了。数组和变量虽然都可以存储,但都不完美。比如:人事关系图、交通图等,

48、都不好用数组保存。从事关系结构只能用“树”还保存,而对于两个起终点:公交线路查询,实现时间最小 / 距离最短 / 花费最低等功能,只能用“图”来存。而图和树都必须有指针知识,它们属于较高深的思想层次的东西。因此要学好数据结构必须要懂得指针。若感兴趣:可以继续学习郝斌老师的数据结构教学视频。链表(较难)C语言和数据结构的连接 ( 过渡 )链表是数据结构第一部分而是 C语言最后一章内容,由此可以比较两者难度算法:通俗定义:解题的方法和步骤狭义定义:对存储数据的操作对不同的存储结构,要完成某一个功能所执行的操作是不一样比如:要输出数组中所有的元素的操作和要输出链表中所有的元素的操作是不一样的这说明:

49、算法是依附于存储结构的不同的存储结构,所执行的算法是不一样的广义定义:广义的算法也叫 泛型 C+无论数据是如何存储的,对该数据的操作都是一样的分层思想,站在更高的层次看,把内部的实现给屏蔽数组和链表都是线性的,都是先输出一个元素后,再输出下一个元素我们至少可以通过两种结构来存储数据数组优点:存取速度快缺点:需要一整块连续的空间插入和删除元素效率很低( 插入和删除中间某个元素,其后的所有都要前后移动)链表优点: 插入删除元素效率高缺点: 查找某个位置的元素效率低(由于不是连续的,不同由下标直接找,必须由头至尾逐一比对查找)两者各有所长,至今没有出现一个更优的存储方式,可集数组、链表优点于一身。链表专业术语 :首结点 :存放第一个有效数据 的结点尾结点:存放最后一个有效数据 的结点,指针域的指针为 NULL,尾结点的标志头结点:头结点的数据类型和首结点的类型是一模一样的头结点是首结点前面的那个节点头结点并 不存在有效数据设置头结点的目的是为了方便对链表的操作头指针:存放头结点地址的指针变量确定一个链表需要一个参数,头指针对于每个链表元素,分为左右两部分,左边为数据单元,右边为下一元素地址。例:#include#includ

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