《(完整)C语言谭浩强学习笔记.pdf》由会员分享,可在线阅读,更多相关《(完整)C语言谭浩强学习笔记.pdf(50页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、天不造人上人,亦不造人下人福泽谕吉 1 C 语言谭浩强版笔记 第一章 程序设计和 C 语言 1、计算机能直接识别和接受的二进制代码称为机器指令,机器指令的集合就是该计算机的机器语言。2、语言的发展历史:机器语言符号语言高级语言 3、高级语言的发展:非结构化语言结构化语言面向对象的语言 4、C 语言的祖先是 BCPL 语言 5、在字符串中的/和/*都不作为注释的开始。而是作为字符串的一部分。【但是在 vc+6.0 中/显示编译错误】6、不要以为在 max 函数中求出最大值 z 后就会自动地作为函数值返回调用处,必须用 return 语句指定将哪个值作为函数值。也不要不加分析地在所有函数后面都写上
2、 return 0 7、一个程序由一个或多个源程序文件组成 8、全局声明:即在函数之外进行的数据声明,在函数外面声明的变量称为全局变量。例如把 int a,b,sum;放到 main 函数的前面 9、函数是 C 程序的主要组成部分,编写 C 程序的工作主要就是编写一个个函数 10、一个 C 语言程序是由一个或多个函数组成的,其中必须有且只有一个 main 函数 11、一个小程序只包含一个源程序文件,在一个源程序文件中包含若天不造人上人,亦不造人下人福泽谕吉 2 干个函数(其中一个为 main 函数),若程序规模太大,可以使一个程序包含若干个源程序文件,每个源程序文件又包含若干个函数【一个源程序
3、文件就是一个程序模块,一个程序分成若干个程序模块】12、在进行编译时是以源程序文件为对象进行的【分别对各源程序文件进行编译得到相应的目标程序,然后再将这些目标程序连接成为一个统一的二进制可执行程序】13、C 语言的这种特点使得容易实现程序的模块化 14、一个函数名后面必须跟一对圆括号,括号内写函数的参数名及其类型。如果函数没有参数,可以写 void 或空括号【如 int main(void)或 int main()】15、void dump()它是一个空函数,但是是合法的 16、程序总是从 mian 函数开始执行的,不管位置在哪儿 17、程序中对计算机的操作是由函数中的 C 语句完成的 18、
4、二进制目标程序在 visual C+中的后缀为.obj 19、可执行程序在 visual C+中的后缀为.exe 20、一个源程序经过编译后得到的目标程序要经过连接阶段与函数库进行连接才能生成可执行文件 21、程序设计的任务:问题分析设计算法编写程序对源程序进行编辑、编译和连接运行程序,分析结果编写程序文档 第二章 算法 1、对数据的描述:在程序中要指定用到哪些数据类型以及这些数据天不造人上人,亦不造人下人福泽谕吉 3 类型和数据的组织形式,这就是数据结构。2、对操作的描述:即要求计算机进行操作的步骤,也就是算法。3、算法+数据结构=程序 4、算法是灵魂,数据结构是加工对象,语言是工具,编程需
5、要采用合适的方法。5、算法的概念:为解决一个问题而采取的方法和步骤。6、计算机算法可分为两大类:数值运算算法和非数值运算算法【数值运算用于求数值解,非数值运算用于事务管理领域】7、算法的特性:有穷性确定性有零个或多个输入有一个或多个输出有效性 8、怎样表示一个算法:自然语言、传统流程图、结构化流程图、伪代码等 9、连接点就是将画在不同地方的流程图连起来,流程图别忘记画箭头。基本结构的特点:只有一个入口只有一个出口结构内的每一部分都有机会被执行到结构内不存在死循环 10、区分当型和直到型:前者先判断条件成不成立,再执行下一步,后者先执行,再判断条件 11、用 N-S 图表示的算法都是结构化的算法
6、,如果一个算法不能分解为若干个基本结构,则它必然不是一个结构化的算法【N-S 图又称盒图】12、结构化设计方法的基本思路:把一个复杂问题的求解过程分阶段天不造人上人,亦不造人下人福泽谕吉 4 进行,每个阶段处理的问题都控制在人们容易理解和处理的范围内。13、方法:自顶向下逐步细化模块化设计结构化编码 14、程序中的子模块一般不超过 50 行 15、模块的独立性:使用一个模块完成一项功能,耦合性越少越好 16、结构化程序设计方法用来解决人脑思维能力的局限性和被处理问题的复杂性之间的矛盾 第三章 最简单的 C 程序设计 1、vc+把所有实数都作为双精度数处理。因此提醒用户:把双精度常量赋给 flo
7、at 型变量会造成精度损失,知道怎么回事就行了 2、数据有两种表现形式:常量和变量 3、常量分为:整型常量(1000)实型常量(十进制小数形式和指数形式【12.34E3,E 后面必须是整数】)字符常量(普通字符、转义字符)字符串常量 符号常量(#define PI 3.1416)4、基本字符集中的每个字符必须用一个字节表示,空字符也占一个字节,它的所有二进制位都是 0 5、一个 tab 位置为 8 列 6、101代表八进制数 101 的 ASCII 字符,即A(十进制65),x41代表十六进制数 41 的 ASCII 字符,也是A,0天不造人上人,亦不造人下人福泽谕吉 5 或者000是代表 A
8、SCII 码为 0 的控制字符,即空操作字符 7、单撇号内只能包含一个字符,双撇号内可以包含一个字符串 8、符号常量不占内存,只是一个临时符号,在预编译后这个符号就不存在了,故不能对符号常量赋以新值 9、变量必须先定义后使用 10、常变量 const int a=3,表示 a 被定义为一个整型变量,指定其值为 3,而且在变量存在期间其值不能改变,常变量不能出现在赋值号的左边。例如上面一行不能写成:const int a;a=3;可以用表达式对常变量初始化,如 const int b=3+6,c=3*cos(1.5);天不造人上人,亦不造人下人福泽谕吉 6 11、标识符只能由字母、数字和下划线组
9、成,且第一个字符必须是字母或下划线 12、基本类型和枚举类型变量的值都是数值,统称为算数类型 算数类型和指针类型统称为纯量类型(因为其变量的值是以数字来表示的)枚举类型是程序中用户定义的整数类型 数组类型和结构体类型统称为组合类型(共用体类型不属于组合类型,因为在同一时间内只有一个成员具有值 13、TC2.0 为每个整型数据分配 2 个字节(16 个二进位);VC+为每个整型数据分配 4 个字节(32 位)14、求负数的补码的方法:先将此数的绝对值写成二进制形式,然后对其后面所有各二进位按位取反,再加 1 15、取值范围 天不造人上人,亦不造人下人福泽谕吉 7 16、如果既未指定为 signe
10、d 也未指定为 unsigned 类型,默认为有符号类型 17、只有整型(包括字符型)数据可以加 signed 或 unsigned 修饰符,实型数据不能加 18、实型数据取值范围:19、在一个整数末尾加大写字母 L 或小写字母 l,表示它是长整型 20、浮点型常量(小数或指数)在内存中都以指数形式储存 21、C 程序中的实型常量都是双精度浮点型常量 float a=3.14159;在进行编译时,对 float 变量分配 4 个字节,但对于浮点型常量3.14159,则按照双精度处理,分配 8 个字符 22、如果除数或被除数中有一个是负值,则舍入的方向不固定,一般采取“向零取整”的方法,即-5/
11、3=-1 23、%运算符要求参加运算的对象是整数,除%以外的运算符的操作数都可以是任何算数类型 24、+i 是先执行 i=i+1 后,再使用 i 的值;而 i+是先使用 i 的值后,再执行 i=i+1。天不造人上人,亦不造人下人福泽谕吉 8 设已作声明:int i=6,a;25、算数表达式和运算符的优先级与结合性 天不造人上人,亦不造人下人福泽谕吉 9 26、不同类型数据间的混合运算规律为:(取精度较高的)+,*,/运算的两个数中有一个为 float 或 double 型,结果是double 型,因为系统将所有 float 型数据都先转换为 double 型,然后进行运算。如果 int 型与
12、float 或 double 型数据进行运算,先把 int 型和float 型数据转换为 double 型,然后进行运算,结果是 double 型。字符(char)型数据与整型数据进行运算,就是把字符的 ASCII 代码与整型数据进行运算。字符型可以直接与整型数据进行运算。如果字符型数据与实型数据进行运算,则将字符的 ASCII 代码转换为double 型数据,然后进行运算。27、强制类型转换:一般形式为(类型名)(表达式),在强制类型转换时,得到一个所需类型的中间数据,而原来的变量的类型未发生变化 28、左值都可以作为右值,但算数表达式(a+b)或常量不能为左值 29、a=(a=b)=3*4
13、;/报错,左侧的操作数必须是左值 天不造人上人,亦不造人下人福泽谕吉 10 30、C 语言的截断 i=289 0000 0001 0010 0001 c=33 0010 0001 31、在 if 条件中可以包含赋值表达式,但不能包含赋值语句 32、一般变量初始化不是在编译阶段完成的【只有在静态储存变量和外部变量的初始化是在编译阶段完成的】,而是在程序运行时执行本函数时赋予初值的,相当于执行一个赋值语句。33、在 scanf 函数中,输入的数字可以用空格分开 34、在 printf 函数中,例如%7.2f 代表在输出时,指定数据占 7 列,其中小数占 2 列 35、C 语言本身不提供输入输出语句
14、(printf 和 scanf 不是 C 语言的关键字。而只是库函数的名字)36、如果在源程序中有 printf 函数,在编译时并不把它翻译成目标指令,而是在连接阶段与系统函数库相连接后,在执行阶段中调用库函数中的 printf 函数 37、头文件称为标准模式,”编译系统先在用户的当前目录查找 38、由于 printf 是函数,因此,“格式控制字符串”和“输出表列”实际上都是函数的参数 39、float 型数据的存储单元只能保证 6 位有效数字,double 是 15天不造人上人,亦不造人下人福泽谕吉 11 位 40、%-m.nf,输出的数据向左对齐 41、e 格式符是以指数形式输出实数,默认
15、小数部分 6 位,指数部分5 列 42、格式字符含义(注意大小写):43、m.n 中的 n 对实数表示输出 n 位小数,对字符串表示截取的字符个数 44、如果想输出字符%,在“”中用连续 2 个%表示:(经检测只输一个不显示)45、在 scanf 函数中,如果两个%f 间有 2 个空格,在输入时,两个数天不造人上人,亦不造人下人福泽谕吉 12 据之间应有 2 个或更多的空格 46、用%c 格式声明输入字符时,空格字符和转义字符中的字符都作为有效字符输入 47、putchar 函数是输出字符的函数,而不是整数,例如 putchar(66)输出字符 B,putchar 可以是字符常量,字符变量,整
16、型常量,整型变量(ASCII 码范围内)48、putchar(getchar();将接收到的字符输出 49、printf(“%c”,getchar();先从键盘输入一个字符,然后用%c的格式输出 第四章 选择结构程序设计 1、if 复合语句应当用花括号括起来 2、所谓关系运算就是比较运算 3、关系运算符中等于与不等于优先级最低 4、算术高于关系高于赋值,关系表达式的值是一个逻辑值,真或假【d=ab;如果 a 大于 b 为真,则 ab 的值为 1,所以 d 为 1】5、逻辑运算符中,非运算符(!)和单目的算术运算符同级,高于双目的算术运算符,优先于关系运算符,优先于逻辑运算符与(&)和或(|)。
17、逻辑运算符中,非运算符(!)的结合性为右结合;与运算(&)和或运算(|)的结合性为左结合。6、0 为假,非 0 为真 7、逻辑表达式注意“短路”现象 天不造人上人,亦不造人下人福泽谕吉 13 8、逻辑型变量(C99,参考):在头文件 stdbool.h 中,将 bool 定义为_Bool 的同义词,同时定义了两个符号常量 true 代表 1,false 代表 2(作用是将关系运算和逻辑运算的结果存到一个逻辑型变量中,以便于分析和运算,定义逻辑变量用类型符_Bool)9、条件运算符由?和:组成,是 C 语言中唯一的一个三目运算符 10、条件与是哪 U 老虎的优先级别比关系运算符和算术运算符低,所
18、以括号可以不要。例如:max=(ab)?a:b+1;可以写成 max=ab?a:b+1;11、if 语句的嵌套:else 总是与它上面的最近的未配对的 if 配对 12、switch 语句中 break 语句的作用是使流程转到 switch 语句的末尾(即由花括号处)13、switch 语句:switch 后面括号内的表达式,其值的类型应当是整数类型(包括字符型)case 后面跟一个常量(或常量表达式)语句体内包含多个以关键字 case 开头的语句行和最多一个以default 开头的行 天不造人上人,亦不造人下人福泽谕吉 14 case 出现次序不影响执行结果,可以先出现 default 标号
19、 在执行 switch 语句中,根据 switch 表达式的值找到匹配的入口标号,并不在此进行条件检查,在执行完一个case 标号后面的语句后,就从此标号开始执行下去,不再进行判断!最后一个 case 子句可不加 break 多个 case 标号可以共用一组执行语句,例如:case a:case b:case c:printf(“60n”);break;如果条件满足,不管是 abc,都输出60 第五章 循环结构程序设计 1、while 语句中循环体只能是一个语句,特点是先判断条件表达式,然后执行循环体语句【while(表达式)语句】2、dowhile 语句的特点是:先执行,再判断【do 语句
20、while(表达式);】3、循环语句中不要忘记给变量赋初始值 4、当 while 后面的表达式的第 1 次的值为“真”时,两种循环得到的结果相同;否则,两者结果不相同(指两者具有相同的循环体的情况)5、for 语句与 while 语句两者无条件等价 6、for 语句若没有表达式 2 或表达式 3,循环体会无止境地执行下去 天不造人上人,亦不造人下人福泽谕吉 15 7、表达式 1 可以是设置循环变量初值的赋值表达式,也可以是与循环变量无关的其他表达式 for(sum=0;i0);printf(“yes”);31、strlen 函数:测字符串实际长度,不包括0,也可以直接测试字符串常量的长度 32
21、、strlwr 函数:将字符串中大写字母转换为小写字母 strupr 函数:将字符串中小写字母转换为大写字母 33、在使用字符串处理函数时,头文件应加入#include 第 7 章 用函数实现模块化程序设计 1、一个 C 程序可由一个主函数和若干个其他函数构成,由主函数调用其他函数,其他函数也可互相调用,同一个函数可以被一个或多个函数调用任意多次 天不造人上人,亦不造人下人福泽谕吉 22 2、函数声明的作用是让系统中编译时知道它们是函数而不是变量或其他对象 3、一个 C 程序由一个或多个程序模块组成,每一个程序模块作为一个源程序文件。由若干个源程序文件组成一个 C 程序,一个源程序文件可以为多
22、个 C 程序共用 4、一个源程序文件由一个或多个函数以及其他有关内容组成。一个源程序文件是一个编译单位,在编译时以源程序文件为单位进行编译,而不是以函数为单位 5、从 main 开始,从 main 结束 6、一个函数并不从属于另一个函数,函数不能嵌套定义(可以嵌套调用)。函数间可以互相调用,但不能调用主函数,mian 函数是被操作系统调用的 7、无参函数可以带回或不带回函数值,但一般不带回,有参函数应定义为与返回值相同的类型 8、定义函数,函数体可以包括声明部分和语句部分 9、调用函数并不一定要求包括分号,只有作为函数调用语句才需要有分号。如果作为函数表达式或函数参数,函数调用本身是不必有分号
23、的 10、定义函数时函数名后面括号中的变量名称为形式参数;在主调函数中调用一个函数时,函数名后面括号中的参数称为实际参数,实参可以是常量、变量或表达式 11、系统会把实参的值传递给被调用函数的形参 天不造人上人,亦不造人下人福泽谕吉 23 12、如果实参与形参类型不同,则按不同类型数值的赋值规则进行转换 13、在定义函数中指定的形参,在未出现函数调用时,他们并不占内存中的存储单元。在发生函数调用时,函数 max 的形参被临时分配内存单元 14、应当注意返回值的类型与函数类型一致 15、形参与实参是两个不同的存储单元 16、实参向形参的数据传递是“值传递”,单向传递,只能由实参传给形参,实参无法
24、得到形参的值 17、函数的返回值是通过函数中 return 语句获得的 18、一个函数可以有一个已上的 return 语句,执行到哪一个 return语句,哪一个 return 语句就起作用。return 语句后面的括号可以不要,return 语句后面的值可以是一个表达式 19、如果函数值的类型和 return 语句中的表达式不一致,则已函数类型为准(不指定函数类型,编译系统默认为 int 型)20、对于不带回值的函数,应当用定义函数为“void 类型”,或空类型 21、用户定义的函数在调用它的函数的后面(同一文件内),应该在主调函数中对被调用函数作声明 22、函数声明比函数定义中的首行多一个
25、分号 23、函数声明中的形参名可以省写,而只写形参的类型。(函数定义应该不能省略)天不造人上人,亦不造人下人福泽谕吉 24 24、如果在文件的开头,对本文件所调用函数进行了声明,则在各函数中不必对其所调用的函数再做声明 25、一个函数内不能再定义另一个函数,也就是不能嵌套定义,但可以嵌套调用函数 26、凡是变量可以出现的地方,都可以用数组元素代替 27、数组名可以作实参和形参,传递的是数组第一个元素的地址。数组元素可以用作函数的实参,不能用作形参。28、数组元素采用的是值传递的方式,方向是从实参传到形参,单向传递 29、用数组元素作实参时,向形参变量传递的是数组元素的值,而用数组名作函数实参时
26、,向形参(数组名或指针变量)传递的是数组首元素的地址 30、实参数组与形参数组类型应一致,如不一致,结果将出错 31、C 语言编译系统并不检查形参数组的大小,只是将实参数组的首元素的地址传给形参数组名,这样两个数组就共占用一段内存单元 32、因此形参数组中各元素的值如果发生变化会使实参数组元素的值同时发生变化 33、多维数组中,在被调用函数中对形参数组定义时可以指定每一维的大小,也可以省略第一维的大小说明 34、中第 2 维大小相同的前提下,形参数组的第 1 维可以与实参数组不同,C 语言编译系统不检查第一维的大小 35、由于 c 语言不支持函数重载(同名),所以在定义和声明时,参天不造人上人
27、,亦不造人下人福泽谕吉 25 数个数,类型,返回值类型不一样就会报这个错误 C2373;全局变量和局部变量重名会报错 修改如下:天不造人上人,亦不造人下人福泽谕吉 26 36、局部变量:在一个函数内部定义的变量只在本函数范围内有效,中复合语句内定义的变量只在本复合语句范围内有效 37、在 x 函数中定义了变量 a,b;在 y 函数中定义了变量 a,c。x 函数的 a 与 y 函数的 a 不是同一个对象 38、主函数定义的变量也只在主函数中有效,主函数也不能使用其他函数中定义的变量 39、形参也是局部变量,例如 x 函数的形参 a 只在 x 函数中有效,其他函数可以调用 x 函数,但不能直接引用
28、 x 函数的形参 a,例如在其他函数中输出 a 的值是不行的 40、全局变量可以为本文件中其他函数所共用。它的有效范围为从定义变量的位置开始到本源文件结束 41、由于同一文件中的所有函数都能引用全部变量的值,因此如果在一个函数中改变了全局变量的值,就能影响到其他函数中全局变量的值(习惯:全局变量名的第一个字母用大写表示)42、若外部变量与局部变量同名:天不造人上人,亦不造人下人福泽谕吉 27 43、全局变量中程序的全部执行过程中都占用存储单元,而不是仅在需要时才开辟单元 44、全局变量全部存放在静态储存区中 45、如果在一个程序中两次调用同一函数,而在此函数中定义了局部变量,在两次调用时分配给
29、这些局部变量的存储空间的地址可能是不相同的 46、每一个变量和函数都有两个属性:数据类型和数据的存储类别。存储类别指的是数据在内存中存储的方式(如静态存储和动态存储)47、函数中的形参和在函数中定义的局部变量(包括在复合语句中定义的局部变量),都属于自动变量(auto)48、不写 auto 则隐含指定为自动存储类型 49、静态局部变量实在编译时赋初值的,只赋值一次,在程序运行时它已有初值,以后每次调用函数时不再重新赋初值而只保留上次函数调用结束时的值。自动变量赋初值,不是在编译时进行的,而是在函数调用时进行的,每调用一次函数重新给一次初值,相当于执行一次赋值语句 50、如果定义局部变量不赋值,
30、对于静态局部变量来说,编译时自动赋值为 0 或0,而对自动变量来说,值不确定 51、静态局部变量在函数调用结束后仍然存在,但只能被本函数引用 52、自动变量 auto 存储动态存储区;静态局部变量 static 存储在静态存储区;寄存器 register 存储在 CPU 中的寄存器 53、用 extern 声明外部变量时,类型名可以写,也可以不写 天不造人上人,亦不造人下人福泽谕吉 28 54、谨慎使用 extern 扩展全局变量的作用域,因为可能会改变该全局变量的值 55、在编译时 extern 时,先在本文件找,再在连接时去其他文件找 56、静态外部变量:用 static 声明,只能用于本
31、文件的外部变量 57、static 的区分:对局部变量来说,把它分配在静态储存区,该变量在整个程序执行期间不释放,其所分配的空间始终存在;对全局变量来说,则该变量的作用域只限于本文件模块 58、报错:重新定义【int a;static a;】正确写法是【static int a】59、从作用域角度分:局部变量,全局变量 从生存期区分:动态存储,静态存储 从变量值存放位置区分:内存中的静态存储区,内存中的动态存储区,CPU 中的寄存器 60、变量着范围内有效符合作用域范围可见可见性 变量在某一时刻存在属于生存期存在 61、凡有 static 声明的,其作用域都是局限的,或者是局限于本函数内(静态
32、局部变量),或者局限于本文件内(静态外部变量)62、把建立存储空间的声明称定义,把不需要建立存储空间的声明称为声明,对外部变量的初始化只能在定义时进行,而不能在声明中进行。结论:在函数中,出现对变量的声明(除 extern 函数)都是定义,在函数中对其他函数的声明不是函数的定义 63、如果不声明,一个文件中的函数既可以被本文件其他函数调用,天不造人上人,亦不造人下人福泽谕吉 29 也可以被其他文件中的函数调用 64、内部函数:一个函数只能被文件中的其他函数所调用 static int fun(int a,int b)64、外部函数:可供其他文件调用 extern int fun(int a,i
33、nt b)C 语言规定,如果定义函数时省略 extern,默认为外部函数,之前都是外部函数 65、宏定义可以用宏名来表示一个字符串,在宏展开时用字符串取代宏名,行末不能加分号,如果加上也是字符串一部分 66、宏定义的作用域是所在位置开始到源程序结束,如果要终止用#undef 命令 67、宏定义允许嵌套,如#define a 3#define b a*3 68、有参宏定义中,宏名和形参表之间不能有空格;带参宏调用中,只是符号替换,不存在值传递问题;宏定义中的形参只能是标识符,而宏调用中的实参可以是表达式,形参要用括号括起来 69、编译预处理指令包含:文件包含,宏定义,条件编译 70、条件编译:(
34、也不知道考不考,详细介绍链接:http:/ 天不造人上人,亦不造人下人福泽谕吉 30 天不造人上人,亦不造人下人福泽谕吉 31 第 8 章 善于利用指针 1、地址指向该变量单元,地址就是指针【指针是一种用来表示地址的类型】2、如果有一个变量专门用来存放另一变量的地址,则它称为“指针变量”,指针变量的值是地址【例如:变量 i 的指针(地址)是 2000,不能说 i 的指针变量是 2000】3、可以理解“*”表示指向,*p 表示指针变量 p 所指向的变量 4、相关程序定义演示:5、可以在定义指针变量时,同时对其初始化 例如:int*c=&a;/定义指针变量 c,并指向 a 6、根据演示,7、8 两
35、行不能写成*c=&a;*d=&b;因为 a 的地址是赋给指针变量 c,而不是赋给*c(即变量 a)7、一个指针变量只能指向同一个类型的变量 8、指针变量只能存放地址,不要将一个整数赋给一个指针变量 9、引用指针变量指向变量:天不造人上人,亦不造人下人福泽谕吉 32 10、函数的参数可以是指针类型,它的作用是将一个变量的地址传送到另一个函数中 11、指针变量在函数调用时,将实参变量的值传递给形参变量,采用的还是值传递。指针变量通过调用函数使变量的值发生变化,在主调函数中可以使用这些改变的值 12、不能通过改变指针形参的值而使指针实参的值改变,因为是值传递,不能通过执行调用函数来改变实参指针变量的
36、值,但是可以改变实参指针变量所指变量的值 13、函数的调用只可以得到一个返回值(即函数值),而使用指针变量做参数,可以得到多个变化了的值 14、注意区分 8.2 和 8.3 的区别,一个是 a,b 值未交换,但是指针指向的地址交换了,所以才改变,后者是值交换了 15、如例 8.5。可以理解为在指针函数中,使用函数后面跟得是指针变量,而不是指针的值,例如定义是 void swap(int*1,int*2),但是使用时是 swap(q1,q2);暂时先这么记 16、数组元素的指针就是数组元素的地址 17、在 C 语言中,数组名(不包括形参数组名,形参数组并不占据实际的内存单元)代表数组中首元素(即
37、序号为 0 的元素)的地址 天不造人上人,亦不造人下人福泽谕吉 33 【=&a0;与 p=a;等价】p=a;的作用是“把 a 数组的首元素的地址赋给指针变量 p”而不是“把数组 a 各元素的值赋给 p”18、int*p=&a0;等价于 int*p;p=&a0;(也可以定义成 int*p=a;/作用是将 a 数组的首元素的地址赋给指针变量 p 而不是赋给*p)19、在指针指向数组元素时,可以对指针进行如下运算:(加一个整数、减一个整数、自加运算、自减运算、两个指针相减)20、如果指针变量 p 已指向数组中的一个元素,则 p+1 指向同一数组中的下一个元素,p-1 指向同一数组中的上一个元素。注意
38、:执行 p+1时并不是将 p 的值(地址)简单地加 1,而是加上一个元素所占用的字节数(p+1 实际代表 p+1*d,d 是字节数)21、如果 p 的初值是&a0,则 p+i 和 a+i 就是数组元素 ai的地址,例如 p+9 和 a+9 的值是&a9,它指向 a9 22、实际上是变址运算符,将 ai按 a+i 计算地址,然后找出地址单元中的值 23、如果指针变量 p1 和 p2 都指向同一数组,p2-p1,结果是 p2-p1的值(两个地址的差)除以数组元素的长度,表示 p2 所指的元素与p1 所指的元素之间差 2 个元素 24、*(p+i)或*(a+i)是 p+i 或 a+i 所指向的数组元
39、素,即 ai。例如:*(p+5)或*(a+5)就是 a5。即*(p+5),*(a+5),a5三者等价 25、可以通过改变指针变量的值指向不同的元素 天不造人上人,亦不造人下人福泽谕吉 34 26、不能用 a+,因为数组名 a 代表数组首元素的地址,它是一个指针型常量,它的值在程序运行期间是固定不变的,a 是常量,a+不合法 27、当指针变量指向数组元素时,指针变量可以带下标。因为在程序编译时,对下标的处理方法是转换为地址的,对 pi处理成*(p+1)28、相关运算区分:p+;*p;p+使 p 指向下一个元素 a1。然后若再执行*p,则得到下一个元素的 a1的值 *p+,因为+与*同优先级,结合
40、方向是自右向左,所以等同于*(p+),先引用 p 的值,实现*p 的运算,然后再使 p 自加 1,这样下一次循环,*p 就是下一个元素的值 *(+p)先使 p 加 1,再取*p,若 p 初值为 a(即&a0),若输出*(p+),得到 a0的值;若输出*(+p),得到 a1的值 +(*p)表示 p 所指向的元素的值加 1,注意是元素的值加 1,而不是指针 p 的值加 1 29、当用数组名作参数时,如果形参数组中各元素的值发生变化,实参数组元素的值随之变化。实参数组名代表该数组首元素的地址,而形参是用来接收从实参传递过来的数组首元素地址的,因此,形参应该是一个指针变量(只有指针变量才能存放地址)f
41、un(int arr,int n)与 fun(int*arr,int n)等价 30、可以理解为形参数组与实参数组共用一个存储单元 31、实参数组名代表一个固定的地址,或者说是指针常量,但形参数天不造人上人,亦不造人下人福泽谕吉 35 组名并不是一个固定的地址,而是按指针变量处理 32、如果一个实参数组,要想在函数中改变此数组中的元素的值,实参与形参的对应关系有 4 种:形参与实参都用数组名 实参用数组名,形参用指针变量 实参形参都用指针变量 实参为指针变量,形参为数组名 (如果用指针变量作实参,必须先使指针变量有确定值,指向一个已定义的对象;已上四种方法都是地址的传递)33、对于二维数组来说
42、,a 代表二维数组首元素的地址,现在的首元素不是一个简单的整型元素,而是由 4 个整型元素所组成的一维数组,例如 a+1 的值是 a1的首地址,a1的值是&a10 34、a0+1 和*(a+0)+1 是 a01的地址,那么*(a0+1)就是a01的值,同理*(*(a+0)+1)或*(*a+1)也是 a01的值 35、a+1 与 a0+1 是不同的,a+1 是序号为 1 的行的首地址,a+1 指向序号为 1 的行;而*(a+1)或 a1或 a1+0 都指向 1 行 0 列的元素,两者虽然地址相同,但是含义不同 36、二维数组名是指向行的,因此 a+1 中的 1 代表一行中全部元素所占的字节数。在
43、指向行的指针前面加一个*,就转为指向列的指针例如a+1 变成*(a+1),它就指向列的指针,指向 1 行 0 列元素的指针反之亦然,a0变成&a0,指向二维数组的 0 行 37、二维数组中,不要简单地认为*(a+i)是 a+i 所指单元中的内容,因天不造人上人,亦不造人下人福泽谕吉 36 为其不是指向具体存储单元而指向行 38、计算 aij在数组中的相对位置的公式为:i*m+j;其中 m 为二维数组的列数 39、p=&a0,则p+1不是指向a01,而是指向a1;如果是p=a0,那 p+1 所指向的元素是 p 所指向的列元素的下一个元素【注意区分】40、int(*p)4表示定义 p 为一个指针变
44、量,它指向包含 4 个整型元素的一维数组。p 被定义为指向一维整型数组的指针变量,一维数组有 4 个元素,因此 p 的基类型是一维数组,其长度是 16 字节 41、实参与形参如果是指针类型,应当注意它们的类型必须一致。不应把 int*型的指针(即元素的地址)传给 int(*)4型(指向一维数组)的指针变量,反之亦然 42、在定义字符数组 string 时未指定长度,由于对它初始化,因此它的长度是确定的,数组名 string 代表字符数组首元素的地址,例如:string7就是*(string+7),string+7 是一个地址 43、在 C 语言中只有字符变量,没有字符串变量 char*stri
45、ng=“I love china”;等价于 char*string;string=“I love china”;44、可以通过字符指针变量输出它所指向的字符串 45、通过字符数组名或字符指针变量可以输出一个字符串;但是数值型数组是不能用数组名输出它的全部元素,它输出的是数组首元素的地址 天不造人上人,亦不造人下人福泽谕吉 37 46、字符复制注意长度,可能有多余的,所以要用%s 格式输出,如果用%c,逐个输出是可以输出后面这些字符的 47、由于字符可以用 ASCII 码代替,所以 while(*from!=0)与 while(*from)是等价的 48、字符数组由若干个元素组成,每个元素中放一
46、个字符,而字符指针变量中存放的是第一个字符的地址,绝不是将字符串放到字符指针变量中。可以对字符指针变量赋值,但不能对数组名赋值,因为数组名是地址,是常量 49、数组可以在定义时对各元素赋初值,但不能用赋值语句对字符数组中全部元素整体赋值 50、编译时为字符数组分配若干存储单元,而对字符指针变量,只分配一个存储单元。如果定义了字符指针变量却没有赋予一个地址值,后果很危险,应当及时指定指向 char*a;str10;a=str;scanf(“&s”,a);先使 a 有确定值,使 a 指向一个数组元素,然后输入一个字符串,把它存放在以该地址开始的若干单元中 天不造人上人,亦不造人下人福泽谕吉 38
47、51、指针变量的值可以改变,数组名不行 输出从 a 指向的字符开始的字符串 52、字符数组中的各元素的值是可以被改变的,但字符指针变量指向的字符串常量中的内容不能被改变,例如;char a=”house”;char*b=”house”;a2=r;/合法 b2=r;/不合法 53、若字符指针变量 p 指向字符串常量,就可以用指针变量带下标的形式引用所指的字符串中的字符 54、可变格式输出函数:例如:char*a=b=%d,c=%dn;也可以 天不造人上人,亦不造人下人福泽谕吉 39 55、函 数 指 针 为 函 数 代 码 存 储 空 间 的 起 始 地 址,格 式:int(*p)(int,in
48、t)指向函数类型为整型且有两个整型参数的函数,注意*p 不能省略,表示 p 先与*结合,是指针变量,()表示是函数 57、函数指针中,p=max 的作用是将函数 max 的入口地址赋给指针变量p,函数名代表该函数的入口地址,因为只能指向入口处,所以*(p+1)不合法 58、定义指向函数的指针变量【类型名指的是函数返回的类型】格式:类型名(*指针变量名)(函数参数表列)59、指向函数的指针变量只能指向在定义时指定的类型的函数,在程序中,一个指针变量可以先后指向同类型的不同函数 60、在给函数指针变量赋值时,只需给出函数名而不必给出参数,例如 p=max;如果写成 p=max(a,b);那就是将调
49、用 max 函数所得到的函数值赋给 p,而不是将函数入口地址赋给 p 61、用函数指针变量调用函数时,只须将(*p)代替函数名即可(p为指针变量名),在(*p)之后的括号中根据需要写上实参 62、对指向函数的指针变量不能进行算术运算 63、指向函数的指针可以作为函数参数,把函数的入口地址传递给形参,这样就能够在被调用的函数中使用实参函数。原理:fun 函数有两个形参 x1 和 x2,定义其为指向函数的指针变量。调用时,实参为两个函数名 f1 和 f2,给形参传递的是函数 f1 和 f2 的入口地址 64、定义返回指针值的函数的一般形式:类型名*函数名(参数表列)天不造人上人,亦不造人下人福泽谕
50、吉 40 第 9 章 用户自己建立数据类型 1、声明一个结构体类型的一般形式:struct 结构体名 成员列表;/成员列表包括:类型名 成员名;2、成员可以属于另一个结构体类型,例如定义一个 struct Date 类型,别的类型在引用时可以是 struct Date 成员名;3、定义结构体类型变量的 3 种方法:先声明结构体类型,再定义该类型的变量 在声明类型的同时定义变量 不指定类型名而直接定义结构体类型变量 天不造人上人,亦不造人下人福泽谕吉 41 4、在定义了结构体变量后,系统会为之分配内存单元 5、结构体类型与结构体变量不同。只能对变量赋值、存取或运算,而不能对一个类型这么做,编译时