目录 10.1 指针的基本概念 10.2 指向变量的指针变量 10.3 指向数组的指针变量 10.4 指向函数的指针变量和指针型函数

Slides:



Advertisements
Similar presentations
第 8 章 数组 计算机科学学院 李淮 Tel QQ
Advertisements

《C语言程序设计》复习
电子成绩单项目实现.
第10章 结构体与链表 本章要点: 结构体类型与结构体变量的定义 结构体变量的引用与初始化 结构体数组 链表处理 共用体类型和枚举类型
C语言程序设计教程 单位:德州学院计算机系.
第8章 指针 ● 8.1 指针简介 ● 8.2 指针变量的操作 ● 8.3 数组与指针 ● 8.4 二维数组与指针 ●本章小结 ●本章练习.
C语言基础——指针的高级应用 Week 05.
第九章 指针 目录 指针与指针变量的概念 变量的指针和指向变量的指针变量 数组的指针和指向数组的指针变量
第九章 系 统 安 全 性 9.1 结构体 9.2 结构体型数组  9.3 结构体型指针 9.4 内存的动态分配 9.5 共用体
第7章 结构体、联合体和枚举类型 本章导读 本章主要知识点 《 C语言程序设计》 (Visual C++ 6.0环境)
第5章 函数与模块化设计 学习目的与要求: 掌握函数的定义及调用方法 理解并掌握参数的传递方法 理解函数的嵌套与递归调用
程序设计基础.
第六章 数 组 主讲教师 贾月乐 联系电话:
C语言程序设计 课程 第5章 数组 主讲:李祥 博士、副教授 单位:软件学院软件工程系.
第5章 函数与预处理 《 C语言程序设计》 (Visual C++ 6.0环境) 本章导读
由C程序结构所知,一个完整的C语言程序是由一个且只能有一个main()函数(又称主函数)和若干个其他函数组合而成的。而前面各章仅学习main()函数的编程,本章将介绍其他函数的编程,包括其他函数的定义、调用、参数传递及变量的作用域等。
C程序设计 第9章 自定义数据类型 主讲教师: 鲁 萍 西安建筑科技大学 理学院.
循环结构又称为重复结构:用来处理需要重复处理的问题,它是程序中一种很重要的结构。
選擇排序法 通訊一甲 B 楊穎穆.
Introduction to the C Programming Language
C 程式設計— 指標.
项目六 用指针优化学生成绩排名 项目要求 项目分析
结构体和共用体 2 梁春燕 华电信息管理教研室.
C 程式設計— 指標 台大資訊工程學系 資訊系統訓練班.
Introduction to the C Programming Language
Introduction to the C Programming Language
目录 第八章 数组 1 简单学生成绩管理系统的开发 2 一维数组 3 多维数组 4 字符数组 5 数组作函数参数.
第七章 函数 目录 有参的加法函数的开发 函数定义的一般形式 函数参数和函数的值 函数的调用
Introduction to the C Programming Language
第三章 C++中的C 面向对象程序设计(C++).
Chap 8 指针 8.1 寻找保险箱密码 8.2 角色互换 8.3 冒泡排序 8.4 电码加密 8.5 任意个整数求和*
C语言程序设计 李祥.
第八章 函数.
第8章 善于利用指针 8.1 指针是什么 8.2 指针变量 8.3 通过指针引用数组 8.4 通过指针引用字符串 8.5 指向函数的指针
第五章 指针 5.1 指针的概念和定义 5.2 指针运算 5.3 指针和数组 5.4 字符串指针 5.5 指针数组 5.6 指向指针的指针
Introduction to the C Programming Language
第6章 函数 学习的意义.
6.4.1指针与二维数组 1、二维数组结构的分析 设有数组定义为:int a[3][4]; 则有: a表示数组在内存中的首地址。
第13章 结构体的应用 13.1 了解由用户构造的数据类型 13.2 结构体类型说明及结构体变量 13.3 结构体数组
第9章 文件操作 文件 使用文件的目的 操作系统管理数据的基本单位 存储在外存储器上的数据的集合
第八章 使用指针.
Introduction to the C Programming Language
第十章 指针.
数组 梁春燕 华电信息管理教研室.
第8章 函数 函数参数和函数的值 概述 函数定义的一般形式 函数的调用(嵌套调用、递归调用) 数组作为函数参数
第十章 用户自定义数据类型 目录 学生信息管理系统的开发 结构体数据类型的概述 结构体变量的使用 结构体数组
目录 9.1 结构体类型 9.2 共用体类型 9.3 枚举类型 9.4 类型声明符typedef 1.
第十章 结构体与链表 西安工程大学.
C语言概述 第一章.
C语言大学实用教程 第5章 函数与程序结构 西南财经大学经济信息工程学院 刘家芬
C语言复习3----指针.
C语言大学实用教程 第6章 数组 西南财经大学经济信息工程学院 刘家芬
函数 概述 模块化程序设计 基本思想:将一个大的程序按功能分割成一些小模块, 特点: 开发方法: 自上向下,逐步分解,分而治之
第八章 指標 (Pointer).
第六章 指针 C++程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值.
7.1 C程序的结构 7.2 作用域和作用域规则 7.3 存储属性和生存期 7.4 变量的初始化
第十章 指针 指针是C语言的重要概念,是C语言的特色,是C语言的精华。 10.1 地址和指针的概念 内存中的每一个字节都有一个地址。
C程序设计.
第九章 指针.
实验七 数 组 第21讲 C程序设计 Main() { int x,y; X=10; y=x*x+1;
C程序设计.
本节内容 指针类型.
第18讲 从C到C++ 计算机与通信工程学院.
Introduction to the C Programming Language
第九章 指针 C程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值.
第9章 C++程序设计初步 9.1 C++的特点 9.2 最简单的C++程序 9.3 C++的输入输出 9.4 函数的重载
第六章 复合数据类型 指针的声明与使用 数组的声明与使用 指针与数组的相互引用 字符串及相关库函数 new与delete
本节内容 指针类型 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
安排座位.
C语言基础学习 从外行到入门.
Presentation transcript:

目录 10.1 指针的基本概念 10.2 指向变量的指针变量 10.3 指向数组的指针变量 10.4 指向函数的指针变量和指针型函数 10.5 指针型数组和指向指针的指针变量 10.6 指向结构体的指针变量 10.7 动态存储分配 1

10.1 指针的基本概念 根据内存单元的地址就可以找到所需的内存单元,通常也把这个地址称为指针。内存单元的地址和内存单元的内容是两个不同的概念,单元的地址即为指针,其中存放的数据才是该单元的内容。 用一个变量来存放指针,这种变量称为指针变量。因此,一个指针变量的值就是某个内存单元的地址或称为某内存单元的指针。为了避免混淆,我们约定:指针是指地址,是常量;指针变量是指取值为地址的变量。 一种数据类型或数据结构往往都占有一组连续的内存单元。指针是一个数据结构的首地址,它是指向一个数据结构的。 2

10.2 指向变量的指针变量 对指向变量的指针变量的定义包括三个内容: 变量的指针就是变量的地址。存放变量地址的变量是指针变量。 10.2 指向变量的指针变量 变量的指针就是变量的地址。存放变量地址的变量是指针变量。 1. 指针变量的定义 对指向变量的指针变量的定义包括三个内容: 1)指针类型声明符,即定义变量为一个指针变量; 2)指针变量名; 3)指针所指向的变量的数据类型。 指针变量定义的一般形式为: 类型声明符 *指针变量名; 其中,*表示这是一个指针变量,类型声明符表示指针变量所指向的变量的数据类型。 应该注意的是,一个指针变量只能指向同类型的变量。 3

2. 指针运算符 10.2 指向变量的指针变量 1)取地址运算符& 用户并不知道变量地址的具体值。 10.2 指向变量的指针变量 2. 指针运算符 用户并不知道变量地址的具体值。 1)取地址运算符& 取地址运算符&是单目运算符,其结合性为自右至左,其功能是取变量的地址。 (1)地址运算符&的一般形式为: &变量名; (2)指针变量的赋值方法 ①指针变量初始化:定义指针变量的同时对其进行初始化。 ②变量地址赋指针变量:把一个变量的地址赋给指向相同数据类型的指针变量。 ③指针变量间相互赋值:把一个指针变量的值赋给指向相同类型变量的另一个指针变量。 注意:不允许把一个数赋给指针变量 。 4

10.2 指向变量的指针变量 2. 指针运算符 2)取内容运算符* 取内容运算符*是单目运算符,结合性为自右至左,表示指针变量所指的变量。 10.2 指向变量的指针变量 2. 指针运算符 2)取内容运算符* 取内容运算符*是单目运算符,结合性为自右至左,表示指针变量所指的变量。 (1)可以通过指针变量间接访问变量 在指针变量定义中,*是类型声明符,表示其后的变量是指针类型。而表达式中出现的*则是一个运算符用以表示指针变量所指的变量。 【例10_1】指针变量初始化。 #include<stdio.h> void main() { int a=5,*p=&a; printf ("%d\n",*p); } 5

10.2 指向变量的指针变量 2. 指针运算符 2)取内容运算符* 【例10_2】变量地址赋指针变量。 10.2 指向变量的指针变量 2. 指针运算符 2)取内容运算符* 【例10_2】变量地址赋指针变量。 #include<stdio.h> void main() { int a,b; int *pointer_1, *pointer_2; a=100;b=10; pointer_1=&a; pointer_2=&b; printf("%d,%d\n",a,b); printf("%d,%d\n",*pointer_1, *pointer_2); } 6

10.2 指向变量的指针变量 2. 指针运算符 2)取内容运算符* (2)指针变量的值是可以改变的,即可以改变它的指向。 10.2 指向变量的指针变量 2. 指针运算符 2)取内容运算符* (2)指针变量的值是可以改变的,即可以改变它的指向。 【例10_3】输入a和b两个整数,按先大后小的顺序输出a和b。 #include<stdio.h> void main() { int *p1,*p2,*p,a,b; scanf("%d,%d",&a,&b); p1=&a;p2=&b; if(a<b) {p=p1;p1=p2;p2=p;} printf("a=%d,b=%d\n",a,b); printf("max=%d,min=%d\n",*p1, *p2); } 7

10.2 指向变量的指针变量 3. 指针变量作为函数参数 函数的参数是指针类型,将一个变量的地址传送到函数中。 10.2 指向变量的指针变量 3. 指针变量作为函数参数 函数的参数是指针类型,将一个变量的地址传送到函数中。 【例10_4】输入的两个整数按大小顺序输出。现在用函数处理,而且用指针类型的数据作函数参数。 #include<stdio.h> swap(int *p1,int *p2) { int temp; temp=*p1; *p1=*p2; *p2=temp; } void main() { int a,b,*pointer_1,*pointer_2; scanf("%d,%d",&a,&b); pointer_1=&a;pointer_2=&b; if(a<b) swap(pointer_1,pointer_2); printf("max=%d,min=%d\n",a,b); } 8

3. 指针变量作为函数参数 10.2 指向变量的指针变量 【例10_5】通过改变指针形参的值不能改变指针实参的值。 10.2 指向变量的指针变量 3. 指针变量作为函数参数 【例10_5】通过改变指针形参的值不能改变指针实参的值。 #include<stdio.h> swap(int *p1,int *p2) { int *p;p=p1;p1=p2;p2=p;} void main() { int a,b; int *pointer_1,*pointer_2; scanf("%d,%d",&a,&b); pointer_1=&a;pointer_2=&b; if(a<b) swap(pointer_1,pointer_2); printf("max=%d,min=%d\n",*pointer_1,*pointer_2); } 9

10.2 指向变量的指针变量 3. 指针变量作为函数参数 【例10_6】输入3个整数a、b、c,按从大到小的顺序输出。 10.2 指向变量的指针变量 3. 指针变量作为函数参数 【例10_6】输入3个整数a、b、c,按从大到小的顺序输出。 #include<stdio.h> swap(int *pt1,int *pt2) { int temp; temp=*pt1; *pt1=*pt2; *pt2=temp; } sort(int *q1,int *q2,int *q3) { if(*q1<*q2)swap(q1,q2); if(*q1<*q3)swap(q1,q3); if(*q2<*q3)swap(q2,q3); } void main() { int a,b,c,*p1,*p2,*p3; scanf("%d,%d,%d",&a,&b,&c); p1=&a;p2=&b; p3=&c; sort(p1,p2,p3); printf("%d,%d,%d \n",a,b,c); 10

10.3 指向数组的指针变量 1. 指针数组的指针变量的定义与赋值 1)指向数组的指针变量的定义形式 类型声明符 *指针变量名; 10.3 指向数组的指针变量 1. 指针数组的指针变量的定义与赋值 1)指向数组的指针变量的定义形式 类型声明符 *指针变量名; 其中类型声明符表示所指数组的类型。应当注意,因为数组为int型,所以指针变量也应为指向int型的指针变量。 2)指向数组的指针变量的赋值 (1)将数组首元素的地址赋给指针变量 (2)将数组名赋给指针变量 (3)在定义指针变量的同时进行初始化 int *p=&a[0];或:int *p=a; p、a、&a[0]均指向同一单元,它们是数组a的首地址,也是0号元素a[0]的首地址。应该声明的是p是指针变量,而a和&a[0]都是地址常量,在编程时应予以注意。 11

10.3 指向数组的指针变量 2. 通过指针变量引用数组 1)指向数组的指针变量加减一个整数n的含义 2)引用一个数组元素的方法 10.3 指向数组的指针变量 2. 通过指针变量引用数组 1)指向数组的指针变量加减一个整数n的含义 设p是指向数组a的指针变量,则p+n、p-n、p++、++p、p--、--p运算都是合法的。指针变量加或减一个整数n的意义是把指针指向的当前位置(指向某数组元素)向前或向后移动n个位置。 如果p的初值为&a[0],则: (1)p+i和a+i就是a[i]的地址,或者说它们指向a数组的第i个元素。 (2)*(p+i)或*(a+i)就是p+i或a+i所指向的数组元素,即a[i]。 (3)指向数组的指针变量也可以带下标,p[i]与*(p+i)等价。 2)引用一个数组元素的方法 (1)下标法:即用a[i]形式访问数组元素。 12

10.3 指向数组的指针变量 2. 通过指针变量引用数组 2)引用一个数组元素的方法 (1)下标法:即用a[i]形式访问数组元素。 10.3 指向数组的指针变量 2. 通过指针变量引用数组 2)引用一个数组元素的方法 (1)下标法:即用a[i]形式访问数组元素。 【例10_7】输出数组中的全部元素。(下标法) #include<stdio.h> void main() { int a[5],i; for(i=0;i<5;i++) a[i]=i; printf("a[%d]=%d\n",i,a[i]); } 13

10.3 指向数组的指针变量 2. 通过指针变量引用数组 2)引用一个数组元素的方法 10.3 指向数组的指针变量 2. 通过指针变量引用数组 2)引用一个数组元素的方法 (2)指针固定法:即采用*(a+i)或*(p+i)形式,用间接访问的方法来访问数组元素,其中a是数组名,p是指向数组首元素的指针变量。 【例10_8】输出数组中的全部元素。(通过数组名计算元素的地址,找出元素的值) #include<stdio.h> void main() { int a[5],i; for(i=0;i<5;i++)*(a+i)=i; for(i=0;i<5;i++) printf("a[%d]=%d\n",i,*(a+i)); } 14

10.3 指向数组的指针变量 2. 通过指针变量引用数组 2)引用一个数组元素的方法 10.3 指向数组的指针变量 2. 通过指针变量引用数组 2)引用一个数组元素的方法 (2)指针固定法:即采用*(a+i)或*(p+i)形式,用间接访问的方法来访问数组元素,其中a是数组名,p是指向数组首元素的指针变量。 【例10_9】输出数组中的全部元素。(用指针变量指向元素,指针变量不动) #include<stdio.h> void main() { int a[5],i,*p; p=a; for(i=0;i<5;i++) *(p+i)=i; for(i=0;i<5;i++) printf("a[%d]=%d\n",i,*(p+i)); } 15

10.3 指向数组的指针变量 2. 通过指针变量引用数组 2)引用一个数组元素的方法 10.3 指向数组的指针变量 2. 通过指针变量引用数组 2)引用一个数组元素的方法 (3)指针移动法:即采用*p++形式,用间接访问的方法来访问数组元素,其中a是数组名,p是指向数组各元素的指针变量。 【例10_10】输出数组中的全部元素。(用指针变量指向元素,指针变量移动) #include<stdio.h> void main() { int a[5],i,*p=a; for(i=0;i<5;) { *p=i; printf("a[%d]=%d\n",i++,*p++); } 16

10.3 指向数组的指针变量 2. 通过指针变量引用数组 4)两指针变量的关系运算 3)两个指针变量之间的相减运算 10.3 指向数组的指针变量 2. 通过指针变量引用数组 3)两个指针变量之间的相减运算 只有指向同一数组的两个指针变量之间才能进行运算,否则运算毫无意义。 两指针变量相减所得之差是两个指针所指数组元素之间相差的元素个数。实际上是两个指针值(地址)相减之差再除以该数组元素的长度(字节数)。 两个指针变量不能进行加法运算,毫无实际意义。 4)两指针变量的关系运算 指向同一数组的两指针变量可以进行关系运算,可表示它们所指向的数组元素位置关系。例如: pf1==pf2表示pf1和pf2指向同一数组元素; pf1>pf2表示pf1处于高地址位置; pf1<pf2表示pf2处于低地址位置。 17

10.3 指向数组的指针变量 2. 通过指针变量引用数组 5)指向数组的指针变量使用注意事项 10.3 指向数组的指针变量 2. 通过指针变量引用数组 5)指向数组的指针变量使用注意事项 (1)指针变量可以实现本身的值的改变,而数组名是数组的首地址,是常量。如p++是合法的;而a++是错误的。 (2)要注意指针变量的当前值。 【例10_11】找出错误。 #include<stdio.h> void main() { int *p,i,a[5]; p=a; for(i=0;i<5;i++)*p++=i; for(i=0;i<5;i++)printf("a[%d]=%d\n",i,*p++); } 18

10.3 指向数组的指针变量 2. 通过指针变量引用数组 5)指向数组的指针变量使用注意事项 【例10_12】改正。 10.3 指向数组的指针变量 2. 通过指针变量引用数组 5)指向数组的指针变量使用注意事项 【例10_12】改正。 #include<stdio.h> void main() { int *p,i,a[5]; p=a; for(i=0;i<5;i++) *p++=i; printf("a[%d]=%d\n",i,*p++); } 19

10.3 指向数组的指针变量 2. 通过指针变量引用数组 5)指向数组的指针变量使用注意事项 10.3 指向数组的指针变量 2. 通过指针变量引用数组 5)指向数组的指针变量使用注意事项 (3)*p++,由于++和*优先级相同,结合方向自右而左,等价于*(p++)。 (4)*(p++)与*(++p)作用不同。若p的初值为a,则*(p++)等价a[0],*(++p)等价a[1]。 (5)(*p)++表示p所指向的元素值加1。 (6)如果p当前指向a数组中的第i个元素,则 *(p--)相当于a[i--]; *(++p)相当于a[++i]; *(--p)相当于a[--i] 20

10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 数组名可以作函数的实参和形参。数组名就是数组的首地址,实参向形参传送数组名实际上就是传送数组的地址,形参得到该地址后也指向同一数组。 指针变量的值也是地址,数组指针变量的值即为数组的首地址,也可作为函数的参数使用。 【例10_13】用指针变量作参数,编写函数求5个学生的平均成绩。 #include<stdio.h> float aver(float *pa); void main() { float sco[5],av,*sp; int i; sp=sco; printf("\ninput 5 scores:\n"); for(i=0;i<5;i++) scanf("%f",&sco[i]); 21

10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 av=aver(sp); 10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 av=aver(sp); printf("average score is %5.2f",av); } float aver(float *pa) { int i; float av,s=0; for(i=0;i<5;i++) s=s+*pa++; av=s/5; return av; 22

10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 【例10_14】将数组a中的n个整数逆序存放。 10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 【例10_14】将数组a中的n个整数逆序存放。 #include<stdio.h> void inv(int x[],int n) /*形参x是数组名*/ { int temp,i,j, m=(n-1)/2; for(i=0;i<=m;i++) { j=n-1-i; temp=x[i]; x[i]=x[j];x[j]=temp; } 23

10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 void main() 10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 void main() { int i,a[10]={3,7,9,11,0,6,7,5,4,2}; printf("the original array:\n"); for(i=0;i<10;i++)printf("%d,",a[i]); printf("\n"); inv(a,10); printf("the array has benn inverted:\n"); for(i=0;i<10;i++) printf("%d,",a[i]); } 24

10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 【例10_15】对例10_14可以作一些改动。将函数inv中的形参x改成指针变量。 #include<stdio.h> void inv(int *x,int n) /*形参x为指针变量*/ { int *p,temp,*i,*j, m=(n-1)/2; i=x;j=x+n-1; p=x+m; for(;i<=p;i++,j--) {temp=*i;*i=*j;*j=temp;} } 25

10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 void main() 10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 void main() { int i,a[10]={3,7,9,11,0,6,7,5,4,2}; printf("the original array:\n"); for(i=0;i<10;i++) printf("%d,",a[i]); printf("\n"); inv(a,10); printf("the array has benn inverted:\n"); for(i=0;i<10;i++)printf("%d,",a[i]); } 26

10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 说明: 10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 说明: (1)在函数max_min_value中求出的最大值和最小值放在max和min中。由于它们是全局,因此在主函数中可以直接使用。 (2)函数max_min_value中的语句: max=min=*array; array是数组,它接收从实参传来的数组numuber的首地址。 *array相当于*(&array[0])。 (3)在执行for循环时,p的初值为array+1,也就是使p指向array[1]。以后每次执行p++,使p指向下一个元素。每次将*p和max与min比较。将大者放入max,小者放min。 (4)函数max_min_value的形参array可以改为指针变量类型。实参也可以不用数组名,而用指针变量传递地址。 27

10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 【例10_17】程序可改为: #include<stdio.h> 10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 【例10_17】程序可改为: #include<stdio.h> int max,min; /*全局变量*/ void max_min_value(int *array,int n) { int *p,*array_end; array_end=array+n; max=min=*array; for(p=array+1;p<array_end;p++) if(*p>max)max=*p; else if (*p<min)min=*p; } 28

10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 void main() { int i,number[10],*p; 10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 void main() { int i,number[10],*p; p=number; /*使p指向number数组*/ printf("enter 10 integer umbers:\n"); for(i=0;i<10;i++,p++) scanf("%d",p); p=number; max_min_value(p,10); printf("max=%d,min=%d\n",max,min); } 29

10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 归纳起来,如果有一个实参数组,想在函数中改变此数组的元素的值,实参与形参的对应关系有以下4种: (1)实参和形参都是数组名; (2)实参用数组,形参用指针变量; (3)实参和形参都用指针变量; (4)实参为指针变量,型参为数组名。 【例10_18】用实参指针变量改写将n个整数按相反顺序存放。 #include<stdio.h> void inv(int *x,int n) { int *p,m,temp,*i,*j;m=(n-1)/2; i=x;j=x+n-1;p=x+m; for(;i<=p;i++,j--) {temp=*i;*i=*j;*j=temp;} } 30

10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 void main() 10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 void main() { int i,arr[10]={3,7,9,11,0,6,7,5,4,2},*p=arr; printf("the original array:\n"); for(i=0;i<10;i++,p++)printf("%d,",*p); printf("\n"); p=arr; inv(p,10); printf("the array has benn inverted:\n"); for(p=arr;p<arr+10;p++)printf("%d,",*p); } 31

10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 【例10_19】用选择法对10个整数排序。 10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 【例10_19】用选择法对10个整数排序。 #include<stdio.h> void main() { int *p,i,a[10]={3,7,9,11,0,6,7,5,4,2}; printf("the original array:\n"); for(i=0;i<10;i++)printf("%d,",a[i]); printf("\n"); p=a;sort(p,10); for(p=a,i=0;i<10;i++) {printf("%d ",*p);p++;} } 32

10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 【例10_19】用选择法对10个整数排序。 10.3 指向数组的指针变量 3.指向数组的指针变量作函数参数 【例10_19】用选择法对10个整数排序。 sort(int *x,int n) { int i,j,k,t; for(i=0;i<n-1;i++) { k=i; for(j=i+1;j<n;j++) if(x[j]>x[k])k=j; if(k!=i) {t=x[i];x[i]=x[k];x[k]=t;} } 33

10.3 指向数组的指针变量 4. 指向多维数组的指针和指向多维数组的指针变量 1)多维数组的地址 10.3 指向数组的指针变量 4. 指向多维数组的指针和指向多维数组的指针变量 1)多维数组的地址 把一个二维数组分解为多个一维数组来处理。因此数组a可分解为三个一维数组,即a[0]、a[1]、a[2]。每一个一维数组又含有4个元素。例如a[0]数组,含有4个元素:a[0][0]、a[0][1]、a[0][2]、a[0][3]。 在二维数组中不能把&a[i]理解为元素a[i]的地址,原因在于根本就不存在元素a[i]。它是一种地址计算方法,表示数组a第i行首地址。 a[0]也可以看成是a[0]+0,是一维数组a[0]的0号元素的首地址,而a[0]+1则是a[0]的1号元素首地址,由此可得出a[i]+j则是一维数组a[i]的j号元素首地址,它等于&a[i][j]。 由a[i]=*(a+i)得a[i]+j=*(a+i)+j。由于*(a+i)+j是二维数组a的i行j列元素的首地址,所以,该元素的值等于*(*(a+i)+j)。 34

10.3 指向数组的指针变量 4. 指向多维数组的指针和指向多维数组的指针变量 1)多维数组的地址 【例10_20】多维数组地址。 10.3 指向数组的指针变量 4. 指向多维数组的指针和指向多维数组的指针变量 1)多维数组的地址 【例10_20】多维数组地址。 #include<stdio.h> void main() { int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11}; printf("%d, %d, %d, %d, %d\n",a,*a,a[0] ,&a[0] , &a[0][0]); printf("%d, %d, %d, %d, %d\n",a+1,*(a+1) ,a[1] , &a[1] ,&a[1][0]); printf("%d, %d\n ",a[1]+1,*(a+1)+1); printf("%d,%d\n",*(a[1]+1),*(*(a+1)+1)); } 35

4. 指向多维数组的指针和指向多维数组的指针变量 10.3 指向数组的指针变量 4. 指向多维数组的指针和指向多维数组的指针变量 2)指向多维数组的指针变量 二维数组指针变量定义的一般形式为: 类型声明符 (*指针变量名)[长度] 其中类型声明符为所指数组的数据类型。“*”表示其后的变量是指针类型。长度表示二维数组分解为多个一维数组时,一维数组的长度,也就是二维数组的列数。应注意(*指针变量名)两边的括号不可少,如缺少括号则表示是指针型数组,意义完全不同。 例如,定义:int (*p)[4];表示p是一个指针变量,它指向包含4个元素的一维数组。若指向第一个一维数组a[0],其值等于a、a[0]或&a[0][0]等。而p+i则指向一维数组a[i]。从前面的分析可得出*(p+i)+j是二维数组i行j列的元素的地址,而*(*(p+i)+j)则是i行j列元素的值。 36

10.3 指向数组的指针变量 4. 指向多维数组的指针和指向多维数组的指针变量 2)指向多维数组的指针变量 10.3 指向数组的指针变量 4. 指向多维数组的指针和指向多维数组的指针变量 2)指向多维数组的指针变量 【例10_21】指向多维数组的指针变量。 #include<stdio.h> void main() { int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11}; int(*p)[4]; int i,j; p=a; for(i=0;i<3;i++) { for(j=0;j<4;j++) printf("%2d ",*(*(p+i)+j)); printf("\n"); } 37

10.3 指向数组的指针变量 5. 字符串的指针和指向字符串的指针变量 1)访问字符串的方法 (1)用字符数组存放一个字符串 10.3 指向数组的指针变量 5. 字符串的指针和指向字符串的指针变量 1)访问字符串的方法 (1)用字符数组存放一个字符串 【例10_22】用字符数组存放一个字符串,然后输出该字符串。 #include<stdio.h> void main() { char string[]=“I like C language!”; printf("%s\n",string); } 38

10.3 指向数组的指针变量 5. 字符串的指针和指向字符串的指针变量 1)访问字符串的方法 (2)用字符串指针变量指向一个字符串 10.3 指向数组的指针变量 5. 字符串的指针和指向字符串的指针变量 1)访问字符串的方法 (2)用字符串指针变量指向一个字符串 ①可以把字符串的首地址赋给指向字符类型的指针变量。 例如: char *pc; pc="c language"; 或用初始化赋值的方法写为: char *pc="c language"; 这里应说明,并不是把整个字符串装入指针变量,而是把存放该字符串的字符数组的首地址装入指针变量。 39

10.3 指向数组的指针变量 5. 字符串的指针和指向字符串的指针变量 1)访问字符串的方法 (2)用字符串指针变量指向一个字符串 10.3 指向数组的指针变量 5. 字符串的指针和指向字符串的指针变量 1)访问字符串的方法 (2)用字符串指针变量指向一个字符串 ①可以把字符串的首地址赋给指向字符类型的指针变量。 【例10_23】用字符串指针变量指向一个字符串。 #include<stdio.h> void main() { char *string=“ I like C language!”; printf("%s\n",string); } 40

10.3 指向数组的指针变量 5. 字符串的指针和指向字符串的指针变量 1)访问字符串的方法 (2)用字符串指针变量指向一个字符串 10.3 指向数组的指针变量 5. 字符串的指针和指向字符串的指针变量 1)访问字符串的方法 (2)用字符串指针变量指向一个字符串 ①可以把字符串的首地址赋给指向字符类型的指针变量。 【例10_24】输出字符串中n个字符后的所有字符。 #include<stdio.h> void main() { char *ps="this is a book"; int n=10; ps=ps+n; printf("%s\n",ps); } 41

10.3 指向数组的指针变量 5. 字符串的指针和指向字符串的指针变量 1)访问字符串的方法 10.3 指向数组的指针变量 5. 字符串的指针和指向字符串的指针变量 1)访问字符串的方法 (2)用字符串指针变量指向一个字符串 ①可以把字符串的首地址赋给指向字符类型的指针变量。 【例10_25】将指针变量指向一个格式字符串,用在printf函数中,用于输出二维数组的各种地址表示的值。但在printf语句中用指针变量pf代替了格式串。 #include<stdio.h> void main() { static int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11}; char *pf; pf="%d,%d,%d,%d,%d\n"; printf(pf,a,*a,a[0],&a[0],&a[0][0]); printf(pf,a+1,*(a+1),a[1],&a[1],&a[1][0]); printf("%d,%d\n",a[1]+1,*(a+1)+1); printf("%d,%d\n",*(a[1]+1),*(*(a+1)+1)); } 42

10.3 指向数组的指针变量 5. 字符串的指针和指向字符串的指针变量 1)访问字符串的方法 10.3 指向数组的指针变量 5. 字符串的指针和指向字符串的指针变量 1)访问字符串的方法 (2)用字符串指针变量指向一个字符串 ②指向字符串的指针变量的定义与指向字符变量的指针变量定义相同,只能根据对指针变量的赋值不同来区别。对指向字符变量的指针变量应赋给该字符变量的地址,如: char c,*p=&c; 表示p是一个指向字符变量c的指针变量。 而:char *s="c language"; 等效于: char *s; s="c language"; 则表示s是一个指向字符串的指针变量。把字符串的首地址赋给s。 43

10.3 指向数组的指针变量 5. 字符串的指针和指向字符串的指针变量 2)使用字符串指针变量与字符数组的区别 10.3 指向数组的指针变量 5. 字符串的指针和指向字符串的指针变量 2)使用字符串指针变量与字符数组的区别 用字符数组和字符指针变量都可实现字符串的存储和运算。但是两者是有区别的。在使用时应注意以下问题: (1)字符串指针变量本身是一个变量,用于存放字符串的首地址;而字符数组的元素是存放在从该首地址开始,并以‘\0’的结束的一块连续的内存空间,即它用来存放整个字符串。 (2)对字符串指针“char *ps=”c language“;” 可以写为“char *ps;ps=”c language“;”; 而对数组“static char st[]={"c language"};” 不能写为“char st[20];st={"c language"};”,只能对字符数组的各元素逐个赋值。 44

1. 指向函数的指针变量 10.4 指向函数的指针变量和指针型函数 1)函数指针变量定义形式 2)把函数的入口地址赋给指向函数的指针变量 10.4 指向函数的指针变量和指针型函数 1. 指向函数的指针变量 1)函数指针变量定义形式 类型声明符 (*指针变量名)(); 其中类型声明符表示被指函数返回值的类型;(*指针变量名)表示“*”后面的变量是定义的指针变量;最后的空括号表示指针变量所指的是一个函数。 2)把函数的入口地址赋给指向函数的指针变量 Int (*pf)(); pf=f; /*f为函数名*/ 表示pf是一个指向函数f入口的指针变量,该函数的返回值是整型,然后通过pf实现对函数f的调用。 3)调用函数的一般形式 (*指针变量名)(实参表) 45

1. 指向函数的指针变量 10.4 指向函数的指针变量和指针型函数 【例10_26】用指针形式实现对函数调用 10.4 指向函数的指针变量和指针型函数 1. 指向函数的指针变量 【例10_26】用指针形式实现对函数调用 #include<stdio.h> int max(int a,int b) { if(a>b)return a; else return b; } void main() { int max(int a,int b); int(*pmax)(); //定义pmax为函数指针变量 int x,y,z; pmax=max; printf("input two numbers:\n"); scanf("%d%d",&x,&y); z=(*pmax)(x,y); printf("maxmum=%d\n",z); 46

1. 指向函数的指针变量 10.4 指向函数的指针变量和指针型函数 4)使用函数指针变量调用函数的步骤 5)使用函数指针变量的注意事项 10.4 指向函数的指针变量和指针型函数 1. 指向函数的指针变量 4)使用函数指针变量调用函数的步骤 (1)先定义函数指针变量,如int (*pmax)(); (2)被调函数的入口地址(函数名)赋给该函数指针变量,如pmax=max; (3)用函数指针变量调用函数,如z=(*pmax)(x,y); 5)使用函数指针变量的注意事项 (1)函数指针变量不能进行算术运算,这是与数组指针变量不同的。数组指针变量加减一个整数可使指针移动指向后面或前面的数组元素,而函数指针的移动是毫无意义的。 (2)函数调用中(*指针变量名)的两边的括号不可少,其中的“*”不应该理解为求值运算,在此处,它只是一种表示符号。 47

1. 指针型函数 10.4 指向函数的指针变量和指针型函数 能够返回指针值的函数称为指针型函数。 1)定义指针型函数的一般形式 10.4 指向函数的指针变量和指针型函数 1. 指针型函数 能够返回指针值的函数称为指针型函数。 1)定义指针型函数的一般形式 类型声明符 *函数名(形参表) { ...... /*函数体*/ } 其中函数名之前加了*号表明这是一个指针型函数,即返回值是一个指针。类型声明符表示了返回的指针值所指向的数据类型。 【例10_27】通过指针型函数,输入一个1~7的整数,输出对应的星期名。 char *day_name(int n) { char *name[]={"illegal day","monday","tuesday","wednesday", "thursday","friday","saturday","sunday"}; return((n<1||n>7)?name[0]:name[n]); 48

1. 指针型函数 10.4 指向函数的指针变量和指针型函数 能够返回指针值的函数称为指针型函数。 1)定义指针型函数的一般形式 10.4 指向函数的指针变量和指针型函数 1. 指针型函数 能够返回指针值的函数称为指针型函数。 1)定义指针型函数的一般形式 #include<stdio.h> #include<stdlib.h> void main() { int i; char *day_name(int n); printf("input day no:\n"); scanf("%d",&i); if(i<0) exit(1); printf("day no:%2d-->%s\n",i,day_name(i)); } 49

1. 指针型函数 10.4 指向函数的指针变量和指针型函数 2)函数指针变量和指针型函数在写法和意义上的区别 10.4 指向函数的指针变量和指针型函数 1. 指针型函数 2)函数指针变量和指针型函数在写法和意义上的区别 (1)int (*p)()是一个变量定义,声明p是一个指向函数入口的指针变量,该函数的返回值是整型量,(*p)的两边的括号不能少。 (2)int *p()则不是变量定义而是函数定义,定义p是一个指针型函数,其返回值是一个指向整型量的指针,*p两边没有括号。作为函数定义,在括号内最好写入形式参数,这样便于与变量定义区别。对于指针型函数定义,int *p()只是函数头部分,一般还应该有函数体部分。 50

10.5 指针型数组和指向指针的指针变量 1. 指针型数组的定义及使用 1)指针型数组定义的一般形式 类型声明符 *数组名[数组长度] 10.5 指针型数组和指向指针的指针变量 1. 指针型数组的定义及使用 1)指针型数组定义的一般形式 类型声明符 *数组名[数组长度] 其中类型声明符为指针值所指向的变量的类型。 【例10_28】通常指针型数组中的每个元素被赋给二维数组每一行的首地址,即让指针型数组指向一个列数组各元素,每列又指向一个行数组。 #include<stdio.h> void main() { int a[3][3]={1,2,3,4,5,6,7,8,9}; int *pa[3]={a[0],a[1],a[2]}; int i,j; 51

10.5 指针型数组和指向指针的指针变量 1. 指针型数组的定义及使用 1)指针型数组定义的一般形式 for(i=0;i<3;i++) 10.5 指针型数组和指向指针的指针变量 1. 指针型数组的定义及使用 1)指针型数组定义的一般形式 for(i=0;i<3;i++) { for(j=0;j<3;j++)printf("%d,%d\t",a[i][j],*(*(a+i)+j)); printf("\n"); } for(j=0;j<3;j++)printf("%d,%d\t",pa[i][j],*(*(pa+i)+j)); 52

10.5 指针型数组和指向指针的指针变量 1. 指针型数组的定义及使用 2)指针型数组和二维数组指针变量的区别 10.5 指针型数组和指向指针的指针变量 1. 指针型数组的定义及使用 2)指针型数组和二维数组指针变量的区别 这两者虽然都可用来表示二维数组,但是其表示方法和意义是不同的。 (1)二维数组指针变量是单个的变量,其一般形式中(*指针变量名)两边的括号不可少。例如:int (*p)[3];表示指向二维数组的指针变量。该二维数组3列或分解为一维数组的长度为3。 (2)指针型数组表示多个指针,在一般形式中*指针型数组名两边不能有括号。例如:int *p[3];表示p是一个指针型数组,有三个下标变量p[0],p[1],p[2]均为指针变量。 3)指针型数组常用来表示一组字符串 指针型数组的每个元素被赋给一个字符串的首地址。指向字符串的指针型数组的初始化更为简单。 53

10.5 指针型数组和指向指针的指针变量 1. 指针型数组的定义及使用 4)指针型数组可以用作函数参数 10.5 指针型数组和指向指针的指针变量 1. 指针型数组的定义及使用 4)指针型数组可以用作函数参数 【例10_29】指针型数组作指针型函数的参数。 #include<stdio.h> #include<stdlib.h> char *day_name(char *name[],int n) { char *pp1,*pp2; pp1=*name; pp2=*(name+n); return((n<1||n>7)? pp1:pp2); } 54

10.5 指针型数组和指向指针的指针变量 1. 指针型数组的定义及使用 4)指针型数组可以用作函数参数 void main() 10.5 指针型数组和指向指针的指针变量 1. 指针型数组的定义及使用 4)指针型数组可以用作函数参数 void main() { char *name[]={"illegal day","monday","tuesday", "wednesday", "thursday","friday","saturday","sunday"}; char *ps; int i; printf("input day no:\n"); scanf("%d",&i); if(i<0) exit(1); ps=day_name(name,i); printf("day no:%2d-->%s\n",i,ps); } 55

10.5 指针型数组和指向指针的指针变量 1. 指针型数组的定义及使用 4)指针型数组可以用作函数参数 10.5 指针型数组和指向指针的指针变量 1. 指针型数组的定义及使用 4)指针型数组可以用作函数参数 【例10_30】输入5个国名并按字母顺序排列后输出。 #include<stdio.h> #include"string.h" void sort(char *name[],int n) { char *pt;int i,j,k; for(i=0;i<n-1;i++) { k=i; for(j=i+1;j<n;j++) if(strcmp(name[k],name[j])>0) k=j; if(k!=i){pt=name[i];name[i]=name[k];name[k]=pt; } } 56

10.5 指针型数组和指向指针的指针变量 2. 指向指针的指针变量 10.5 指针型数组和指向指针的指针变量 2. 指向指针的指针变量 如果一个指针变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针的指针变量。 1)指向指针型数据的指针变量的定义 类型声明符 **指向指针的指针变量名 其中类型声明符为指针变量所指向指针的类型。 例如:char **p;p前面有两个*号,相当于*(*p)。显然*p是指针变量的定义形式,如果没有最前面的*,那就是定义了一个指向字符数据的指针变量。现在它前面又有一个*号,表示指针变量p是指向一个字符指针型变量的。*p就是p所指向的另一个指针变量。 2)指向指针型数据的指针变量的使用 指针型数组的每一个元素是一个指针型数据,其值为地址。可以设置一个指针变量p,使它指向指针型数组元素,p就是指向指针型数据的指针变量。 57

10.5 指针型数组和指向指针的指针变量 2. 指向指针的指针变量 2)指向指针型数据的指针变量的使用 10.5 指针型数组和指向指针的指针变量 2. 指向指针的指针变量 2)指向指针型数据的指针变量的使用 【例10_31】使用指向指针的指针变量。 #include<stdio.h> void main() { char *name[]={"follow me","c++","great wall", "computer desighn"}; char **p; int i; for(i=0;i<4;i++) { p=name+i; printf("%s\n",*p); } 说明:在该程序中,p是指向指针的指针变量。 58

10.5 指针型数组和指向指针的指针变量 2. 指向指针的指针变量 2)指向指针型数据的指针变量的使用 10.5 指针型数组和指向指针的指针变量 2. 指向指针的指针变量 2)指向指针型数据的指针变量的使用 【例10_32】一个指针型数组的元素指向数据的简单例子。 #include<stdio.h> void main() { static int a[5]={1,3,5,7,9}; int *num[5]={&a[0],&a[1],&a[2],&a[3],&a[4]}; int **p,i;p=num; for(i=0;i<5;i++) { printf("%4d",**p); p++; } printf("\n"); 59

10.5 指针型数组和指向指针的指针变量 3. main函数的参数 1)main函数的形参 10.5 指针型数组和指向指针的指针变量 3. main函数的参数 1)main函数的形参 C语言规定main函数的参数只能有两个,习惯上这两个参数写为argc和argv。因此,main函数的函数首部可写为: main(argc,argv) C语言还规定argc(第一个形参)必须是整型变量,argv(第二个形参)必须是指向字符串的指针型数组。加上形参说明后,main函数的函数首部应写为: main(int argc,char *argv[]) argv参数是字符串指针型数组,其各元素值为命令行中各字符串(参数均按字符串处理)的首地址。指针型数组的长度即为参数个数,数组元素初值由系统自动赋给。 60

10.5 指针型数组和指向指针的指针变量 3. main函数的参数 2)main函数的实参 10.5 指针型数组和指向指针的指针变量 3. main函数的参数 2)main函数的实参 由于main函数不能被其它函数调用,因此不可能在程序内部取得实参值。实际上,main函数的参数值是从操作系统命令行上获得的。当我们要运行一个可执行文件时,在dos提示符下键入文件名,再输入实参即可把这些实参传送到main的形参中去。 (1)dos提示符下命令行的一般形式 d:\>可执行文件名 参数 参数…… 但是应该特别注意的是,main的两个形参和命令行中的参数在位置上不是一一对应的。因为,main的形参只有二个,而命令行中的参数个数原则上未加限制。argc参数表示了命令行中参数的个数(注意:文件名本身也算一个参数),argc的值是在输入命令行时由系统按实际参数的个数自动赋给的。 61

10.5 指针型数组和指向指针的指针变量 3. main函数的参数 【例10_33】main函数的形参。 10.5 指针型数组和指向指针的指针变量 3. main函数的参数 【例10_33】main函数的形参。 #include<stdio.h> void main(int argc,char *argv[]) { while(argc-->1) printf("%s\n",*++argv); } 本例是显示命令行中输入的参数。如果本例的可执行文件名为10_33.exe,存放在d盘debug文件夹内,输入的命令行为: d:\debug>10_33 teacher help student 62

10.5 指针型数组和指向指针的指针变量 3. main函数的参数 10.5 指针型数组和指向指针的指针变量 3. main函数的参数 由于文件名10_33本身也算一个参数,所以共有4个参数,执行main时,argc的初值即为4。argv的4个元素分别为4个字符串的首地址。执行while语句,每循环一次,argv值减1,当argv等于1时停止循环,共循环3次,因此共可输出3个参数。在printf函数中,由于输出项“*++argv”是先加1再输出,故第一次输出的是argv[1]所指的字符串teacher,第二、三次循环分别输出后2个字符串;而参数10_33是文件名,不输出。 (2)在Visual C++6.0环境下对程序编译和连接后,选择工程->设置->调试->程序变量命令,输入要输出的字符串,如teacher help student,然后再运行程序,将会得到运行结果: 63

10.6 指向结构体的指针变量 1. 指向结构体变量的指针变量 1)指向结构体变量的指针变量的定义 2)指向结构体变量的指针变量的赋值 10.6 指向结构体的指针变量 1. 指向结构体变量的指针变量 1)指向结构体变量的指针变量的定义 结构体指针变量定义的一般形式为: struct 结构体名 *结构体指针变量名 例如,在前面的例题中定义了stu这个结构体,如要声明一个指向stu的指针变量pstu,可写为:struct stu *pstu; 当然也可在定义stu结构体时同时声明pstu。 2)指向结构体变量的指针变量的赋值 结构体指针变量必须要先赋值后才能使用。赋值是把结构体变量的首地址赋给该指针变量,不能把结构体名赋给该指针变量。如果student是被声明为stu类型的结构体变量,则:pstu=&student是正确的,而:pstu=&stu是错误的。结构体名只能表示一个结构体形式,编译系统并不对它分配内存空间。只有当某变量被声明为这种类型的结构体时,才对该变量分配存储空间。 64

10.6 指向结构体的指针变量 1. 指向结构体变量的指针变量 3)指向结构体变量的指针变量的成员访问 10.6 指向结构体的指针变量 1. 指向结构体变量的指针变量 3)指向结构体变量的指针变量的成员访问 有了结构体指针变量,就能更方便地访问结构体变量的各个成员。其访问的一般形式为: (*结构体指针变量).成员名 或为:结构体指针变量->成员名 例如:(*pstu).num或者:pstu->num 应该注意“(*pstu)”两侧的括号不可少,因为成员符“.”的优先级高于“*”。如去掉括号写作“*pstu.num”则等效于*(pstu.num) 。 【例10_34】结构体指针变量的声明和使用。 #include<stdio.h> struct stu { int num;char *name; float score; } student1={102,"zhang",78.5},*pstu; 65

10.6 指向结构体的指针变量 1. 指向结构体变量的指针变量 3)指向结构体变量的指针变量的成员访问 void main() 10.6 指向结构体的指针变量 1. 指向结构体变量的指针变量 3)指向结构体变量的指针变量的成员访问 void main() { pstu=&student1; printf("number=%d\tname=%s\tscore=%f\n", student1.num,student1.name,student1.score); printf("number=%d\tname=%s\tscore=%f\n ", (*pstu).num,(*pstu).name,(*pstu).score); pstu->num,pstu->name,pstu->score); } 66

10.6 指向结构体的指针变量 1. 指向结构体变量的指针变量 3)指向结构体变量的指针变量的成员访问 10.6 指向结构体的指针变量 1. 指向结构体变量的指针变量 3)指向结构体变量的指针变量的成员访问 本例程序定义了一个结构体stu,定义了stu类型结构体变量student1并作了初始化赋值,还定义了一个指向stu类型结构体的指针变量pstu。在main函数中,pstu被赋给student1的地址,因此pstu指向student1。然后在printf语句内用三种形式输出student1的各个成员值。 从运行结果可以看出: 结构体变量.成员名 (*结构体指针变量).成员名 结构体指针变量->成员名 这三种用于表示结构体成员的形式是完全等效的。 67

10.6 指向结构体的指针变量 2. 指向结构体数组的指针变量 10.6 指向结构体的指针变量 2. 指向结构体数组的指针变量 指针变量可以指向一个结构体数组,这时结构体指针变量的值是整个结构体数组的首地址。结构体指针变量也可指向结构体数组的一个元素,这时结构体指针变量的值是该结构体数组元素的首地址。 设ps为指向结构体数组的指针变量,则ps也指向该结构体数组的0号元素,ps+1指向1号元素,ps+i则指向i号元素。这与普通数组的情况是一致的。 68

10.6 指向结构体的指针变量 2. 指向结构体数组的指针变量 【例10_35】用指针变量输出结构体数组。 10.6 指向结构体的指针变量 2. 指向结构体数组的指针变量 【例10_35】用指针变量输出结构体数组。 #include<stdio.h> struct stu { int num; char *name; float score; }student[3]={ {101,"zhou",45}, {102,"zhang",62.5}, {103,"liu",92.5}, }; 69

10.6 指向结构体的指针变量 2. 指向结构体数组的指针变量 【例10_35】用指针变量输出结构体数组。 void main() 10.6 指向结构体的指针变量 2. 指向结构体数组的指针变量 【例10_35】用指针变量输出结构体数组。 void main() { struct stu *ps; printf("no\tname\tscore\n"); for(ps=student;ps<student+3;ps++) printf("%d\t%s\t%f\n",ps->num, ps->name,ps->score); } 在程序中,定义了stu结构体类型的外部数组student并作了初始化赋值。在main函数内定义ps为指向stu类型的指针。在循环语句for的表达式1中,ps被赋给student的首地址,然后循环3次,输出student数组中各成员值。 70

10.6 指向结构体的指针变量 2. 指向结构体数组的指针变量 10.6 指向结构体的指针变量 2. 指向结构体数组的指针变量 应该注意的是,一个结构体指针变量虽然可以用来访问结构体变量或结构体数组元素的成员,但是,不能使它指向一个成员。也就是说不允许取一个成员的地址来赋给它。因此,下面的赋值是错误的。 ps=&student[1].sex; 而只能是: ps=student; //赋给数组首地址 或者是: ps=&student[0]; //赋给0号元素首地址 71

10.6 指向结构体的指针变量 3. 结构体指针变量作函数参数 10.6 指向结构体的指针变量 3. 结构体指针变量作函数参数 C语言允许用结构体变量作函数参数进行整体传送,但是这种传送要将全部成员逐个传送,特别是成员为数组时将会使传送的时间和空间开销很大,严重地降低了程序的效率。因此最好的办法就是使用指针,即用指针变量作函数参数进行传送。这时由实参传向形参的只是地址,从而减少了时间和空间的开销。 【例10_36】计算一组学生的平均成绩和不及格人数,用结构体指针变量作函数参数编程。 #include<stdio.h> struct stu {int num;char *name; float score; }student[3]={{101,"zhou",45}, {102,"zhang",62.5}, {103,"liu",92.5} }; 72

10.6 指向结构体的指针变量 3. 结构体指针变量作函数参数 void ave(struct stu *ps) 10.6 指向结构体的指针变量 3. 结构体指针变量作函数参数 void ave(struct stu *ps) { int c=0,i;float ave,s=0; for(i=0;i<3;i++,ps++) { s+=ps->score; if(ps->score<60) c+=1; } printf("s=%f\n",s); ave=s/3; printf("average=%f\ncount=%d\n",ave,c); void main() { struct stu *ps;ps=student; ave(ps); 73

10.7 动态存储分配 1.分配内存空间函数malloc() 1)调用形式 2)功能 (类型声明符*)malloc(size) 10.7 动态存储分配 1.分配内存空间函数malloc() 1)调用形式 (类型声明符*)malloc(size) 其中,类型声明符表示把该区域用于何种数据类型;(类型声明符*)表示把返回值强制转换为该类型指针;size是一个无符号数。 2)功能 在内存的动态存储区中分配一块长度为size字节的连续区域,函数的返回值为该区域的首地址。例如: pc=(char *)malloc(100); 表示分配100个字节的内存空间,并强制转换为字符数组类型,函数的返回值为指向该字符数组的指针,把该指针赋给指针变量pc。 74

10.7 动态存储分配 2.分配内存空间函数calloc() 1)调用形式 2)功能 calloc也用于分配内存空间。 10.7 动态存储分配 2.分配内存空间函数calloc() calloc也用于分配内存空间。 1)调用形式 (类型声明符*)calloc(n,size) 2)功能 在内存动态存储区中分配n块长度为size字节的连续区域。函数的返回值为该区域的首地址。 calloc函数与malloc函数的区别仅在于一次可以分配n块区域。 例如: ps=(struct stu*)calloc(2,sizeof(struct stu)); 其中的sizeof(struct stu)是求stu的结构体长度。该语句的功能是:按stu的长度分配2块连续区域,强制转换为stu类型,并把其首地址赋给指针变量ps。 75

10.7 动态存储分配 3.重新分配内存空间函数realloc() 4.释放内存空间函数free() 1)调用形式 2)功能 10.7 动态存储分配 3.重新分配内存空间函数realloc() realloc也用于分配内存空间。 1)调用形式 (类型声明符*)recalloc(*p,size) 2)功能 将p所指向的由malloc或calloc函数所分配的动态存储区域的大小改变为size字节。p的值不变。 4.释放内存空间函数free() free(void*p); 释放p所指向的一块内存空间,p是一个任意类型的指针变量,它指向被释放区域的首地址。 76

10.7 动态存储分配 3.重新分配内存空间函数realloc() 【例10_37】分配一块区域,输入一个学生数据。 10.7 动态存储分配 3.重新分配内存空间函数realloc() 【例10_37】分配一块区域,输入一个学生数据。 #include<stdio.h> #include<stdlib.h> void main() { struct stu {int num;char *name;float score;} *ps; ps=(struct stu*)malloc(sizeof(struct stu)); ps->num=102;ps->name="zhang ping"; ps->score=62.5; printf("number=%d\nname=%s\n",ps->num,ps->name); printf("score=%f\n",ps->sex,ps->score); free(ps); } 77