《指针、函数及自定义数据类型.ppt》由会员分享,可在线阅读,更多相关《指针、函数及自定义数据类型.ppt(37页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第第3 3章章 指针、函数、及其他数据类型指针、函数、及其他数据类型指针指针函数函数结构体结构体共用体共用体枚举枚举3.1 3.1 指针指针指针是一种非常重要的数据类型,利用指针变量可以表示指针是一种非常重要的数据类型,利用指针变量可以表示各种数据结构,方便地引用数组和字符串,像汇编语言各种数据结构,方便地引用数组和字符串,像汇编语言一样处理内存地址。指针极大地丰富了语言的功能,一样处理内存地址。指针极大地丰富了语言的功能,运用指针编程是语言最主要的风格之一。运用指针编程是语言最主要的风格之一。3.1.1 3.1.1 指针的基本概念指针的基本概念指针变量的定义指针变量的定义数据类型符数据类型符
2、*指针变量名指针变量名;int*p;double*pd;int*p1,*p2;int*p1,p2;3.1.1 3.1.1 指针的基本概念指针的基本概念&取地址运算符和取地址运算符和*取值运算符取值运算符int n;int*pn;pn=&n;*pn=2;3.1.1 3.1.1 指针的基本概念指针的基本概念指针的运算指针的运算指针是一个内存地址值,它是一个无符号的整数,可以指针是一个内存地址值,它是一个无符号的整数,可以进行加法和减法运算,但不允许进行乘法、除法和两个进行加法和减法运算,但不允许进行乘法、除法和两个指针值的相加运算。指针类型的变量在内存中都和指针值的相加运算。指针类型的变量在内存中
3、都和int类类型所占的大小想相同型所占的大小想相同,可以使用可以使用sizeof来查看大小来查看大小 int a5=1,2,3,4,5;int*p1=&a1;p1+;3.1.1 3.1.1 指针的基本概念指针的基本概念void指针类型指针类型void*p;上面的定义中,上面的定义中,p仍然是一个指针变量,有自己的内存仍然是一个指针变量,有自己的内存空间,占用空间,占用4个字节,但是没有指定它指向哪种类型的个字节,但是没有指定它指向哪种类型的变量。在这种情况下,不能对指针变量进行运算,否则变量。在这种情况下,不能对指针变量进行运算,否则会导致编译错误。会导致编译错误。3.1.1 3.1.1 指针
4、的基本概念指针的基本概念指针的类型转换指针的类型转换(TYPE*)p 强制类型转换的结果是生成一个新的指针,该指针的类强制类型转换的结果是生成一个新的指针,该指针的类型为型为TYPE*,所指向的类型为,所指向的类型为TYPE,其他属性都不变,其他属性都不变,所指向的地址仍为原来的地址。所指向的地址仍为原来的地址。3.1.1 3.1.1 指针的基本概念指针的基本概念指向指针的指针指向指针的指针数据类型符数据类型符*指向指针的指针变量名指向指针的指针变量名;int a,b;int*p;int*pp;p=&a1&a为变量为变量a的地址的地址,即指针变量即指针变量p指向整型的变量指向整型的变量app=
5、&p;2&p为指针变量为指针变量p的地址的地址,即指向指针变量的指针变量即指向指针变量的指针变量pp指向指针变量指向指针变量p*pp=6;问上面的语局同什么语句相同问上面的语局同什么语句相同?*pp=&b问上面的语句同什么语句相同问上面的语句同什么语句相同?3.1.2 3.1.2 指针与数组的互操作指针与数组的互操作数组名和指针变量是两个不同的概念,数组名和指针变量是两个不同的概念,但他们都可以用来但他们都可以用来对数组或数组元素进行引用。数组名实际上就是数组的对数组或数组元素进行引用。数组名实际上就是数组的首地址首地址int a10;int*p;p=a;p=&a0;对数组元素的引用既可以使用
6、下标法,也可以使用指针的对数组元素的引用既可以使用下标法,也可以使用指针的表示方法,如:表示方法,如:p+n与与a+n表示数组元素表示数组元素an的地址,即的地址,即&an*(p+n)和和*(a+n)表示数组的元素表示数组的元素an3.1.3 3.1.3 指针数组指针数组指针变量也可以作为数组元素,进而构成指针数组。指针变量也可以作为数组元素,进而构成指针数组。char*week=Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday;3.2 3.2 函数函数函数的定义与声明函数的定义与声明函数的调用与参数传递函数的调用与参数传递变量的
7、作用域变量的作用域变量的存储类型变量的存储类型外部函数和内部函数外部函数和内部函数函数的递归函数的递归函数指针函数指针3.2.1 3.2.1 函数的定义与声明函数的定义与声明函数对应于程序的模块,需要先定义后使用。定义也叫函数的声明函数对应于程序的模块,需要先定义后使用。定义也叫函数的声明,函数的声明函数的声明需要注意的是函数句尾有一个分号需要注意的是函数句尾有一个分号,并且形式参数可以只写数据类型并且形式参数可以只写数据类型返回值类型符返回值类型符 函数名函数名(形式参数列表形式参数列表)定义部分定义部分;执行语句部分执行语句部分;return语句的格式为:语句的格式为:return 表达式
8、表达式;return(表达式表达式);3.2.2 3.2.2 函数的调用与参数传递函数的调用与参数传递函数调用的一般格式为:函数调用的一般格式为:函数名函数名(实际参数列表实际参数列表)函数参数传递是调用函数和被调用函数在调用发生时进行通信的方法。基本的参函数参数传递是调用函数和被调用函数在调用发生时进行通信的方法。基本的参数传递机制有:数传递机制有:值传递值传递:被调用函数中的任何操作都不会影响到实参变量的值被调用函数中的任何操作都不会影响到实参变量的值地址传递地址传递:被调用函数队形式参数的任何擦操作做都被处理成间接寻被调用函数队形式参数的任何擦操作做都被处理成间接寻址址,通过对地质访问通
9、过对地质访问,会影响实际参数变量会影响实际参数变量通过指针的方式实现了地质的传递通过指针的方式实现了地质的传递,但这种地质传递方式实际上也是但这种地质传递方式实际上也是值传递值传递,只不过传递的是地址值只不过传递的是地址值3.2.3 3.2.3 变量的作用域变量的作用域局部变量是局部变量是在函数内部定义的变量或函数的形式参数。在函数内部定义的变量或函数的形式参数。int func(int a,int b)int i;int main()int i,j;3.2.3 3.2.3 变量的作用域变量的作用域全局变量是在函数外部定义的变量全局变量是在函数外部定义的变量 int x,y;void func
10、()int main()/*int y;*/现在全局变量现在全局变量x,y在两个函数中都可以使用在两个函数中都可以使用,需要注意的是需要注意的是,如果在函数内部定义变如果在函数内部定义变量和全局变量名相同量和全局变量名相同,又或者是函数参数中有和全局变量名相同又或者是函数参数中有和全局变量名相同,则会使用局部则会使用局部变量变量.3.2.3 3.2.3 变量的作用域变量的作用域如果需要在未定义前使用全局变量如果需要在未定义前使用全局变量,声明全局变量:声明全局变量:extern 数据类型符数据类型符 全局变量名全局变量名;使用全局变量可以减少函数调用过程中实际参数和形式参使用全局变量可以减少函
11、数调用过程中实际参数和形式参数之间数据传递带来的时间消耗。但也会带来了一些问数之间数据传递带来的时间消耗。但也会带来了一些问题题全局变量破坏了函数的封装性全局变量破坏了函数的封装性 全局变量使函数代码的可读性降全局变量使函数代码的可读性降 3.2.4 3.2.4 变量的存储类型变量的存储类型定义一个变量的完整形式应为:定义一个变量的完整形式应为:存储类型说明符存储类型说明符 数据类型符数据类型符 变量名变量名;存储类型说明符有四种:存储类型说明符有四种:auto(自动变量)(自动变量)extern(外部变量)(外部变量)static(静态变量)(静态变量)register(寄存器变量)(寄存器
12、变量)变量的存储类型变量的存储类型变量在内存中的存储方式可以分为两种变量在内存中的存储方式可以分为两种,静态存储和动态存储静态存储和动态存储静态存储静态存储:变量在定义的时候就分配存储单元并一直保持到整个程序的结束全局变量在定义的时候就分配存储单元并一直保持到整个程序的结束全局变量即属于静态存储的方式变量即属于静态存储的方式动态存储动态存储:在程序执行过程中在程序执行过程中,使用它时才分配存储单元使用它时才分配存储单元,使用完立即释放使用完立即释放.函数的函数的形式参数形式参数,在定义的时候不会分配内存空间在定义的时候不会分配内存空间,只要被调用的时候只要被调用的时候,才进行内存的才进行内存的
13、分配分配,如果一个函数被反复调用如果一个函数被反复调用,则会反复地进行存储单元的分配与释放则会反复地进行存储单元的分配与释放通常把由于变量的存储方式不同而产生的特性成为变量的生存期通常把由于变量的存储方式不同而产生的特性成为变量的生存期,生存期表示了生存期表示了变量存在的时间变量存在的时间,也叫生命周期也叫生命周期.生命周期和作用域是从时间和空间两个不同的角度来描述变量的特性生命周期和作用域是从时间和空间两个不同的角度来描述变量的特性C语言中存储类型分为四种语言中存储类型分为四种变量的存储类型变量的存储类型一一 自动变量自动变量默认的情况下默认的情况下,所有的局部变量都是自动变量所有的局部变量
14、都是自动变量auto int a int a 是相同的关键字可以省略是相同的关键字可以省略二二 外部变量外部变量全局变量的存储方式全局变量的存储方式,都是外部变量都是外部变量,使用使用extern关键字声明关键字声明,全局是从作用域角全局是从作用域角度说的度说的,外部是从存储方式说的外部是从存储方式说的.所谓的外部就是所谓的外部就是,该类型的变量可以在所有构该类型的变量可以在所有构成程序的源文件中使用成程序的源文件中使用三三 静态变量静态变量static关键声明关键声明,重要的是重要的是,他对于修饰局部变量和全局变量含义是不一样的他对于修饰局部变量和全局变量含义是不一样的extern int
15、a 全局变量全局变量,可以在多个源文件中使用可以在多个源文件中使用static extern int a 也是全局变量也是全局变量,但是只是本文件的全局变量但是只是本文件的全局变量,不能再其它文件不能再其它文件中使用中使用,静态全局变量静态全局变量static 修饰局部变量修饰局部变量,特点是特点是,该变量位于静态存储区该变量位于静态存储区,在整个程序运行期间始终在整个程序运行期间始终占用着被分配的空间占用着被分配的空间.也就是说也就是说,在函数调用后在函数调用后,他的值依然存在他的值依然存在,并可能会影并可能会影响下一次函数的调用响下一次函数的调用四四 寄存器变量寄存器变量变量一般是存放在内
16、存中的变量一般是存放在内存中的,但是对于一些频繁使用的变量但是对于一些频繁使用的变量,为了提高存取时为了提高存取时间间,可将其放入在可将其放入在CPU的寄存器中的寄存器中.叫寄存器变量叫寄存器变量.register int i.一般来说没一般来说没必要这么声明必要这么声明,编辑器会优化变量的声明编辑器会优化变量的声明,并自动识别并自动识别,转换成寄存器变量转换成寄存器变量3.2.5 3.2.5 外部函数和内部函数外部函数和内部函数当一个程序由多个源文件组成时,可以指定一个文件中的当一个程序由多个源文件组成时,可以指定一个文件中的函数能被其他文件调用,也可以指定该函数只能被本文函数能被其他文件调
17、用,也可以指定该函数只能被本文件使用。从这个意义上讲,函数可以分为:件使用。从这个意义上讲,函数可以分为:外部函数外部函数:默认就是外部函数默认就是外部函数 extern关键字关键字内部函数内部函数:static关键字来声明关键字来声明3.2.5 3.2.5 外部函数和内部函数外部函数和内部函数如果一个函数可以被其他源文件调用,该函数就称为外部如果一个函数可以被其他源文件调用,该函数就称为外部函数。定义外部函数时,在函数前面加关键字函数。定义外部函数时,在函数前面加关键字extern。extern int add(int a,int b)return a+b;3.2.5 3.2.5 外部函数和
18、内部函数外部函数和内部函数如果一个函数只能被本文件中的其他函数调用,该函数就如果一个函数只能被本文件中的其他函数调用,该函数就称为内部函数。定义内部函数时,在函数前面加关键字称为内部函数。定义内部函数时,在函数前面加关键字static。static int add(int a,int b)return a+b;3.2.6 3.2.6 函数的递归函数的递归所谓递归,就是函数自己调用自己,或在自己调用的下一所谓递归,就是函数自己调用自己,或在自己调用的下一级函数中调用自己。函数的递归之所以能实现,就是因级函数中调用自己。函数的递归之所以能实现,就是因为函数在每次调用时都在栈中有形参和局部变量的拷贝
19、,为函数在每次调用时都在栈中有形参和局部变量的拷贝,他们与函数的其他调用过程无关。他们与函数的其他调用过程无关。采用递归的方法解决实际问题时,必须满足一定的条件:采用递归的方法解决实际问题时,必须满足一定的条件:可以把要解决的问题转化为一个新的问题,而新问题的可以把要解决的问题转化为一个新的问题,而新问题的解决方法与原问题相同,只是所处理的对象有规律地递解决方法与原问题相同,只是所处理的对象有规律地递增或递减;增或递减;要有递归结束的条件,即在适当的地方结束递归调用,要有递归结束的条件,即在适当的地方结束递归调用,否则将进入死循环。否则将进入死循环。3.2.7 3.2.7 函数指针函数指针函数
20、指针是指向函数的指针函数指针是指向函数的指针变量变量。因而因而“函数指针函数指针”本身首先应是本身首先应是指针变量指针变量,只,只不过该指针变量指向函数。这正如用指针变量可指向不过该指针变量指向函数。这正如用指针变量可指向整型变量整型变量、字符型、字符型、数数组组一样,这里是指向函数。如前所述,一样,这里是指向函数。如前所述,C在编译时,每一个函数都有一个入在编译时,每一个函数都有一个入口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量口地址,该入口地址就是函数指针所指向的地址。有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其他类型变量一样,后,可用该
21、指针变量调用函数,就如同用指针变量可引用其他类型变量一样,在这些概念上是一致的。函数指针有两个用途:调用函数和做函数的在这些概念上是一致的。函数指针有两个用途:调用函数和做函数的参数参数。函数指针变量的定义格式为:函数指针变量的定义格式为:函数的返回值类型函数的返回值类型(*函数指针变量名函数指针变量名)(函数的形式参数函数的形式参数)void(*p)(int x);int func(int x);/*声明一个函数声明一个函数*/int(*f)(int x);/*声明一个函数指针声明一个函数指针*/定义一个指针变量定义一个指针变量f,它指向某一个函数它指向某一个函数,这种函数返回值类型是这种函
22、数返回值类型是int,并且参数类型并且参数类型是是int类型类型,这里只是定义这里只是定义,并未赋值并未赋值f=func;/*将将func函数的首地址赋给指针函数的首地址赋给指针f*/赋值时函数赋值时函数func不带括号,也不带参数,由于不带括号,也不带参数,由于func代表函数的首地址,因此经过代表函数的首地址,因此经过赋值以后,指针赋值以后,指针f就指向函数就指向函数func(x)的代码的首地址。的代码的首地址。(*f)(9)通过函数指针调用了通过函数指针调用了func函数指针函数指针函数指针也可以作为函数的参数使用函数指针也可以作为函数的参数使用tpyedef关键字关键字typedef
23、类型类型 别名别名例例typedef int int32;int32 a=9;上面的上面的int32就变成了一种类型就变成了一种类型,它指代的是它指代的是int类型类型typedef void(*pt)(int,int)上面的含义是定义一个函数指针类型上面的含义是定义一个函数指针类型 ptvoid add(int,int);void sub(int,int);void fun(pt,int,int);定义一个函数定义一个函数,其中一个参数是指针类型其中一个参数是指针类型pt3.3 3.3 结构体、共用体和枚举结构体、共用体和枚举前面介绍的数据类型(如字符型、整型、数组和指针等)前面介绍的数据类
24、型(如字符型、整型、数组和指针等)只能描述事物某一方面的属性。而现实世界中的事物往只能描述事物某一方面的属性。而现实世界中的事物往往具有多方面的属性,为此往具有多方面的属性,为此C语言提供几种用户可以自语言提供几种用户可以自定义的数据类型:结构体、共用体和枚举。定义的数据类型:结构体、共用体和枚举。3.3.1 3.3.1 结构体结构体结构类型体的定义结构类型体的定义struct 结构体名结构体名 数据类型符数据类型符 成员成员1;数据类型符数据类型符 成员成员2;数据类型符数据类型符 成员成员n;3.3.1 3.3.1 结构体结构体结构体变量的定义结构体变量的定义 先定义结构体,然后像定义基本
25、数据类型变量一样,定先定义结构体,然后像定义基本数据类型变量一样,定义结构体类型的变量义结构体类型的变量 在定义结构体的同时定义结构体变量,适用于定义局部在定义结构体的同时定义结构体变量,适用于定义局部使用的结构体变量使用的结构体变量 直接定义结构体变量,即在定义结构体的同时定义结构直接定义结构体变量,即在定义结构体的同时定义结构体变量,但不给出结构体名体变量,但不给出结构体名 3.3.1 3.3.1 结构体结构体结构体变量的初始化结构体变量的初始化struct 结构体名结构体名 结构体变量名结构体变量名=初始数据表初始数据表;struct student a=23,Zhang Xing,M,
26、28,1002 Xin Jian Road;3.3.1 3.3.1 结构体结构体指向结构体的指针指向结构体的指针struct 结构体名结构体名*结构体指针名结构体指针名struct student*p;3.3.1 3.3.1 结构体结构体结构体变量成员的引用结构体变量成员的引用结构体变量名结构体变量名.成员名成员名a.id(*结构体指针变量结构体指针变量).成员名成员名(*p).id 结构体指针变量结构体指针变量-成员名成员名 p-id 3.3.1 3.3.1 结构体结构体嵌套结构体嵌套结构体struct student int id;char name20;char sex;unsigned
27、 int age;struct addr address;结构体变量名结构体变量名.嵌套结构体变量名嵌套结构体变量名.结构体成员名结构体成员名 struct address char city32;char address100;unsigned long zipcode;char tel8;3.3.1 3.3.1 结构体结构体应用实例应用实例3.3.2 3.3.2 共用体共用体共用体又称为联合体,它也是由不同类型的数据构成的。共用体又称为联合体,它也是由不同类型的数据构成的。共用体和结构体的主要区别是:共用体存储时采用了覆共用体和结构体的主要区别是:共用体存储时采用了覆盖技术,不同数据类型的
28、成员占用同一段内存空间。这盖技术,不同数据类型的成员占用同一段内存空间。这样在某一时间点上,共用体中只能存储其某一成员的信样在某一时间点上,共用体中只能存储其某一成员的信息。息。3.3.2 3.3.2 共用体共用体共用体类型的定义共用体类型的定义union 共用体名共用体名 数据类型符数据类型符 成员成员1;数据类型符数据类型符 成员成员2;数据类型符数据类型符 成员成员n;共用体变量的定义共用体变量的定义 union 共用体名共用体名 共用体变量名共用体变量名;3.3.3 3.3.3 枚举枚举枚举是一个被命名的整型常量的集合,其中列举出所有可枚举是一个被命名的整型常量的集合,其中列举出所有可
29、能的取值。能的取值。枚举类型的定义枚举类型的定义enum 枚举名枚举名 枚举常量枚举常量1,枚举常量枚举常量2,枚举常量枚举常量n;枚举变量的定义枚举变量的定义enum枚举名枚举名 枚举变量名枚举变量名;3.4 3.4 小结小结介绍介绍C语言中的指针、函数、结构体、共用体和枚举等内语言中的指针、函数、结构体、共用体和枚举等内容,他们是容,他们是C语言学习中的重点和难点部分。指针是一语言学习中的重点和难点部分。指针是一种特殊的变量,务必深刻理解其类型、所指向的类型、种特殊的变量,务必深刻理解其类型、所指向的类型、值等相关概念,否则在使用过程中很容易出现错误,而值等相关概念,否则在使用过程中很容易出现错误,而且这些错误往往很难发现。指针与数组、函数、结构体且这些错误往往很难发现。指针与数组、函数、结构体等相结合,可以使程序的实现更加灵活多样,在编程实等相结合,可以使程序的实现更加灵活多样,在编程实践中应注意体会。践中应注意体会。