




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、2022-3-51C语言程序设计 2022-3-52第五章 一级指针与一维数组主讲主讲: : 计算机学院计算机学院 吴敏吴敏天使与魔鬼的化身指针 指针: 铁杆C/C+程序员最挚爱的武器 指针造就了C/C+的高效和强大,很多不可能的任务由指针完成 黑客攻击服务器利用的bug绝大部分都是指针和数组造成的这 “该程序执行了非法操作,即将关闭”种错误几乎全是由指针和数组导致的2010年5月10日星期一内存地址内存:计算机内的存储部件,活动中程序指令和数据都保存在内存中速度快、但是掉电即失内存中的每个字节都有唯一的一个地址, 地址是一个无符号整数(通常用16进制数)只要指明要访问的内存单元的地址,就可以
2、立即访问到该单元可以认为:地址和指针是同义词,变量的指针就是变量的地址2010年5月10日星期一指针的故事 地下工作者阮小二接到上级指令,要去寻找打开密电码的密钥,这是一个整数。几经周折,才探知如下线索,密钥藏在一栋三年前就被贴上封条的小楼中。一个风雨交加的夜晚,阮小二潜入了小楼,房间很多,不知该进哪一间,正在一筹莫展之际,忽然走廊上的电话铃声响起。阮小二抓起听筒,只听一个陌生人说:“去打开211房间,那里有线索”。阮小二疾步上楼,打开211房门,用电筒一照,桌上隐约显现:1000。阮小二眼睛一亮,迅速找到1000房间,取出重要数据66,完成了任务。2010年5月10日星期一故事说明重要数据藏
3、在一个内存地址单元中,地址是1000。地址1000又由另一单元P所指认,P单元的地址为211。66的直接地址是1000;66的间接地址是211,因为211单元中存的是直接地址1000。我们称P为指针变量,1000是指针变量的值,实际上是有用数据藏在地址为1000的存储器中。. .10002116610002010年5月10日星期一指针的概念 指针变量:用来存放另一变量地址的变量(内存地址),简称指针 指针是对一种特殊变量的称呼,其特殊性表现在类型(运算)和值上。变量数组字符串函数指针常量2010年5月10日星期一指针既然是变量,所以也具有变量的三个要素:变量的名称。命名规则与一般变量一样,是由
4、英文字符或下划线开始的。变量的类型。“X型指针”、“指向X类型的指针”。变量的值。有特殊含义-是某个内存地址。指针定义类型 *标识符int *pi, *pc;2010年5月10日星期一这里的&是取地址运算符,&i表示取变量i的地址int *pi = &i;表示定义一个指向int型的指针变量pi,并用i的地址来初始化pipi是变量, int *是类型变量占用内存空间,pi的大小是sizeof(int *)指针所指变量int i = 0;int *pi = &i;char c =a;char *pc = &c;c:97i:0.pc:0 x804a0024pi
5、:0 x804a00200 x804a00240 x804a00200 x804a00140 x804a00102010年5月10日星期一示例#include /*演示指针的定义*/int main( ) int i=0;char c=a; int*pi; char *pc;pi = &i;pc = &c;printf(变量t内容tt地址n);printf(-n);printf(it%dtt%pn,i, &i);printf(ct%ctt%pn,c, &c);printf(pit%pt%pn,pi, &pi);printf(pct%pt%pn,pc, &
6、amp;pc);printf(-n);printf(pi=%dtpc=%cn, *pi, *pc);return 0; pointer1.c2010年5月10日星期一NULL是一个等于0的常量,在头文件stddef.h中定义, 它是唯一的一个允许直接赋值给指针的整数值空指针int *p = NULL; 表示指针不指向任何内存地址 防止其指向任何未知的内存区域 把指针初始化为 NULL 是好习惯, 可以避免产生难以预料的错误发生2010年5月10日星期一指针的作用与意义 指针的最根本意义在于:使程序可以通过地址访问数据和函数。2010年5月10日星期一关于指针的原则 学习原则 一定要学会 其实通
7、常的应用很简单,就是一个变量 复杂的应用也不建议使用 使用原则 永远要清楚每个指针指向了哪里 远要清楚指针指向的位置是什么2010年5月10日星期一指针使用注意事项:指针使用注意事项:(1)指针变量前面的指针变量前面的“*”,表示该变量类型为指针类型。,表示该变量类型为指针类型。例例: float *pointer_1;指针变量名是;指针变量名是pointer_1 ,而不是,而不是* pointer_1 。 (2) 在定义指针变量时必须指定基类型。在定义指针变量时必须指定基类型。需要特别注意的是,只有整型变量的地址才能放到指向需要特别注意的是,只有整型变量的地址才能放到指向整型变量的指针变量中
8、。下面的赋值是错误的整型变量的指针变量中。下面的赋值是错误的 float a; int * pointer_1; pointer_1=&a; (3)不要将一个整数(或任何其他非地址类型的数据)赋给指针变量)如果已执行了语句 pointer_;对对“”和和“* *”运算符说明:运算符说明:n存在的存在的等价关系:等价关系: n(1 1)pointer_1= =&a; pointer_1= =&a; n(2 2) * * pointer_1pointer_1 =a ; =a ; n(3 3)& &* * pointer_1 pointer_1 = point
9、er_1 ; = pointer_1 ; n(4 4) * *& pointer_1& pointer_1 = pointer_1 = pointer_1 n(5 5) * *&a=a&a=an但是:但是:& &* *a=a; a=a; 却是错误的,却是错误的,因为因为a a不代表地址,所以不代表地址,所以* *a a无意义无意义。int i,*p;p=&i; int *p;float *q;p=q;int i;float *p;p=&i;int *p;p=100;指针变量只指针变量只存放地址存放地址!一个指针变量不能一个指针变量
10、不能指向与其类型不同指向与其类型不同的变量的变量!我是真的,我是真的,你猜对了吗?你猜对了吗?应在类型相应在类型相同的指针变同的指针变量之间赋值量之间赋值指针运算2010年5月10日星期一取地址运算符& &运算符用来取被操纵对象的地址 例如: &x表示变量x在内存的存放地址,若x的地址0 xbfff0010, 则&x的值就是0 xbfff0010。 &的优先级是14。2010年5月10日星期一取值运算符* *运算访问指针所指变量。 例如: x=*p是将指针p所指变量的值赋给x *p=5是将5送入指针p所指变量中 *的优先级也为142010年5月10日星期
11、一& 与 * 的关系#include /*演示指针的定义*/int main( )int * p = NULL;int i = 0;int a5=0,0,0,0,0;p = &i;*p = 1;printf(i = %dn, i);p = a;*p = 2;printf(a0 = %dn, a0);p = &a0;*p = 3;printf(a0 = %dn, a0);p = &a4;*p = 4;printf(a4 = %dn, a4);return 0; &和*互为逆运算 &是取地址运算符,操作对象是变量,&运算的结果指向该变量的指针
12、 *是取值运算符,操作对象是地址,*运算访问地址表达式所指变量pointer2.c2010年5月10日星期一 指针变量中只能存放地址,因此,在使用中不要将一个整数赋给一指针变量指针赋值#include /*演示指针的赋值*/int main( ) int a = 66; int *p=NULL; int *q=NULL; p = a; q = 66; p = &a; /将变量 a 的地址赋给 p q = p; / 将 p 的值赋给 q printf(%d %d %dn, a, *p, *q); return 0;pointer3.c2010年5月10日星期一指针运算法则 只能进行加减和
13、关系运算 +、- =!= 只能同类型指针之间或指针与整数之间运算2010年5月10日星期一数组下标范围数组下标范围0-0-4 4 C语言为这些数据,提供了一种构造数据类型:语言为这些数据,提供了一种构造数据类型:数组。所谓数组。所谓数组就是一组具有相同数据类型的数据数组就是一组具有相同数据类型的数据的有序集合。的有序集合。n一个班学生的学习成绩一个班学生的学习成绩n一行文字一行文字n一个矩阵一个矩阵这些数据的特点是:这些数据的特点是:- -批量处理数据批量处理数据1.1.具有相同的数据类型具有相同的数据类型2.2.使用过程中需要保留原始数据使用过程中需要保留原始数据1. 格式:类型说明符类型说
14、明符 数组名常量表达式;数组名常量表达式;例如: int aint a1010; ; 它表示定义了一个整形数组,数组名为它表示定义了一个整形数组,数组名为a a,此数组有,此数组有1010个个元素。元素。1 1、一维数组的定义、一维数组的定义1. 1.数组名定名规则和变量名相同,遵循标识符定名规则。数组名定名规则和变量名相同,遵循标识符定名规则。2.2.在定义数组时,需要指定数组中元素的个数。在定义数组时,需要指定数组中元素的个数。方括弧中的常量表达式用来表示元素的个数,即数组长度。方括弧中的常量表达式用来表示元素的个数,即数组长度。3.3.常量表达式中不能包含变量。常量表达式中不能包含变量。
15、 C C语言不允许对数组的大小作动态定义,即数组的大小不依语言不允许对数组的大小作动态定义,即数组的大小不依赖于程序运行过程中变量的值。赖于程序运行过程中变量的值。 int n; int n; scanf( scanf(“%d%d,&n); &n); int a int an n; ; float afloat a0 0; int b(2); int b(2); int k, ak;int k, ak; 常见错误:常见错误:每个数据元素占用每个数据元素占用的字节数,就是的字节数,就是基基类型类型的字节数的字节数一个元素占一个元素占4个字节个字节一维数组:一维数组: float
16、mark100;float mark100;mark0mark1mark2mark3. . . .mark9986.592.077.552.0. . . .94.0低地址低地址 高地址高地址2 2、一维数组的存放规律、一维数组的存放规律注意:注意:1、定义数组时用到的“数组名常量表达式” 和引用数组元素时用到的“数组名下标” 是有区别的。例如例如 int a10; t=a6; 2、数组不能整体引用,每次只能引用数组的一个元数组不能整体引用,每次只能引用数组的一个元素。素。 数组名下标数组名下标下标可以是整型常量或整型表达式。下标可以是整型常量或整型表达式。例如例如: : a0=a5+a7-a2
17、*32 2、一维数组元素的引用、一维数组元素的引用#include #include void main()void main() int i int i,a a1010; ; for (i=0; i=9;i+) for (i=0; i=0; i-) for(i=9;i=0; i-) printf(%d printf(%d ,a ai i);); printf(n); printf(n); 运行结果如下:运行结果如下:9 8 7 6 5 4 3 2 1 09 8 7 6 5 4 3 2 1 0 程序使程序使a0到到a9的值为的值为09,然后按逆序输出。然后按逆序输出。例如例如:int a:in
18、t a1010=0,1,2,3,4,5,6,7,8,9;=0,1,2,3,4,5,6,7,8,9;将数组元素的初值依次放在一对花括弧内。经过上面的定义和初始化之后,a0=0,a1=1,a2=2,a3=3,a4=4,a5=5,a6=6,a7=7,a8=8,a9=9。 4 4、一维数组元素的初始化、一维数组元素的初始化n 1. 1.在定义数组时对数组元素赋以初值。在定义数组时对数组元素赋以初值。例如例如: int a: int a1010=0=0,1 1,2 2,3 3,4; 4; 定义定义a a数组有数组有1010个元素,但花括弧内只提供个元素,但花括弧内只提供5 5个初值,这表示只给个初值,这
19、表示只给前面前面5 5个元素赋初值,后个元素赋初值,后5 5个元素值为个元素值为0 0。n2.2.在定义数组时只给一部分元素赋值。在定义数组时只给一部分元素赋值。 int a int a1010=0,0,0,0,0,0,0,0,0,0;=0,0,0,0,0,0,0,0,0,0; 或或int aint a1010=0;=0; 不能写成:不能写成:int aint a1010=0=0* *10;10;n 3.3.如果想使一个数组中全部元素值为如果想使一个数组中全部元素值为0 0,可以写成,可以写成: : 例如例如: :int aint a5 5=1=1,2 2,3 3,4 4,5;5;int ai
20、nt a=1=1,2 2,3 3,4 4,5; 5; int aint a1010=1=1,2 2,3 3,4 4,5; 5; 只初始化前5个元素,后5个元素为0。n 4.4.对全部数组元素赋初值可以不指定数组长度。对全部数组元素赋初值可以不指定数组长度。数组的输入和输出 数组输入int array3; int i;for(i = 0; i 3; i+) scanf(%d, &arrayi);int array3;int i; scanf(%d %d %d, &array); 数组输出int array3;int i; for(i = 0; i 3; i+)printf(%d,
21、 arrayi); int array3;int i; printf(%d, array); 11年4月6日星期三数据下标越界问题 C语言不检查数组下标的越界。如果定义数组 int a10,合法的下标范围是0 9,但如果你引用a10,系统不会报错,但是程序非常容易出现异常 解决方法:程序员在对下标变量进行操作前,仔细检查下标的合法性11年4月6日星期三请点评#include int main()int i;int a3 = 111, 222, 333;for (i = 1; i = 3; i+) ai = 0; printf(%dn, ai);return(0);overflow.c11年4月
22、6日星期三指针与数组2010年5月10日星期一指针与数组 指针与数组有着密切的关系 数组名是数组的首地址,指针值也是一个地址则p与a表示 如果指针指向数组的首地址,例p指向a0,的是同一个对象 事实上,在C中把数组名可以看作常量指针 指针也可当作数组名使用2010年5月10日星期一指针与数组等价之处 注意: ai,pi, *(a+i), *(p+i)等价#include /*演示指针标识数组*/int main( ) int i=0; int *p = NULL; int a5=0,1,2,3,4; p = a; for(i=0; i5; i+) printf(a%d = %d %d %d %
23、dn, i, ai, pi, *(a+i), *(p+i); pointer4.c return 0;2010年5月10日星期一表表5.2 5.2 数组元素及元素地址的表示(数组元素及元素地址的表示(数组定义:数组定义:int a5;int a5;)表示表示 意义意义 等价表示等价表示 a a 数组第一个元素的地址,是指针常量数组第一个元素的地址,是指针常量 &a0&a0a+i(0i4) a+i(0i4) 第第i+1i+1个元素的地址,是指针常量表个元素的地址,是指针常量表达式,不可被修改达式,不可被修改 &ai &ai &ai(0i4)&ai(
24、0i4)a+i a+i * *(a+i)(0i4)(a+i)(0i4) 第第i+1i+1个元素的间接引用表达,是基个元素的间接引用表达,是基类型的变量类型的变量 ai ai ai(0i4)ai(0i4)第第i+1i+1个元素的下标(索引)表达,个元素的下标(索引)表达,是基类型的变量是基类型的变量 * *(a+i) (a+i) 总结:总结:一维数组元素的一维数组元素的地址地址有两种等价表示:有两种等价表示:a+i= =&aia+i= =&ai;一维;一维数组数组元素元素有两种等价表示:有两种等价表示:* *(a+i)= ai(a+i)= ai指针与数组不同之处 指针是一个变量
25、数组名不是一个变量,是一个常量指针 定义数组分配空间由类型和下标决定,定义指针仅仅分配指针类型空间int *p;int a=1,2,3;a = p;a+;int *p;int a=1,2,3;p = a;p+;2010年5月10日星期一字符指针#include /*演示字符指针和字符串*/int main() char *sp = I Love China; char *sv = NULL; char str = I am a student; sv = sp; sp = str; printf(%sn, sp); printf(%sn, sv); return 0; 字符串实际上是常量字符数
26、组在C语言中,除了用字符数组表示字符串,还可以用字符指针来表示字符串编译系统为sp、sv分配指针类型空间并初始化,为str分配字符型空间并初始化char_pointer.c2010年5月10日星期一str是一个仅仅足以存放初始化字符串及空字符0的一维数组,数组中的字符元素可以修改,但是str始终指向同一地址sp是一个指针,其初值指向一个字符串常量,之后它可以被修改已指向任何其它地址。字符指针与字符数组的区别char str = I Love China;char *sp = I Love China;IL o v eC h i n a 0L o v eC h i n a 0str: Isp:2
27、010年5月10日星期一请点评#include /*演示字符指针和字符串*/int main() char *sp; char str14; sp = C Programming; str= C Programming; printf(%sn, sp); printf(%sn, str); return 0; array_error.c2010年5月10日星期一请点评 注意数组名是常量指针,不能改变array_error.c#include /*演示字符指针和字符串*/int main() char *sp; char str14; sp = C Programming; str= C Pro
28、gramming; printf(%sn, sp); printf(%sn, str); return 0; 2010年5月10日星期一n1 1、表示、表示“数组数组”这个整体概念这个整体概念n2 2、表示该数组的位置,即数组第一个元素的地址,此、表示该数组的位置,即数组第一个元素的地址,此时时a a的值等于的值等于a0a0这个元素的物理地址,此时这个元素的物理地址,此时a+ia+i的数值的数值等于等于aiai这个元素的物理地址,这个元素的物理地址,* *(a+i)(a+i)表示表示aiai这个元这个元素的间接表示方法,如下图示意:素的间接表示方法,如下图示意:n从键盘上输入从键盘上输入101
29、0个整数,输出这些元素及其中正数和负个整数,输出这些元素及其中正数和负数的个数(请用数组实现)数的个数(请用数组实现)#include #include int main()int main() int a10,i; int a10,i; int positive=0,negative=0; int positive=0,negative=0; printf(Please input 10 elements:n);printf(Please input 10 elements:n);for (i=0;i10;i+) for (i=0;i10;i+) scanf(%d,&ai); sca
30、nf(%d,&ai); for (i=0;i10;i+)for (i=0;i0) positive+; if(ai0) positive+; else if (ai0) negative+ ;else if (ai0) negative+ ;for (i=0;i10;i+) for (i=0;i10;i+) printf(%d,ai);printf(%d,ai);printf(n positive number are %d,negative number are printf(n positive number are %d,negative number are %dn,posit
31、ive,negative);%dn,positive,negative);return 0;return 0; n程序程序5.35.3从键盘上输入从键盘上输入n(1n10)n(1n10)个整数,求出最大值个整数,求出最大值n思路思路:(1 1)首先需要定义数组以存储)首先需要定义数组以存储n n个整数,再用一层循环输出元素值个整数,再用一层循环输出元素值(2 2)然后用一层循环作统计、找最大值)然后用一层循环作统计、找最大值(3 3)最后输出结果)最后输出结果 #include #include int main()int main() int a10,i,n; int a10,i,n; in
32、t max; int max; dodo printf(Please input n(1=n=10):n);printf(Please input n(1=n=10):n);scanf(%d,&n);scanf(%d,&n);while (n10);while (n10);printf(Please input %d elements:n,n);printf(Please input %d elements:n,n);for (i=0;in;i+) for (i=0;in;i+) max=a0 ;max=a0 ; for (i=1;in; i+) for (i=1;imax)
33、max=(a+i)max) max=* *(a+i);(a+i); printf(max element=%dn,max);printf(max element=%dn,max);return 0;return 0; 数组首元素地址可以传给?数组首元素地址可以传给?基类型相同的指针变量基类型相同的指针变量地址传递地址传递 例:例:int a5;int a5; int int * *p=a;p=a;注意:注意: p p是变量,是变量,也可以获得任意元素的地址值,也可以获得任意元素的地址值,例:例:p=&a2 p=&a2 此时此时:p0:p0等价于等价于* *p p或或a2a2,
34、p2p2等价于等价于* *(P+2)P+2)或或a2a2 a0a1a2a3a3a4a413ff58app0p1p2p3p3p4p413ff58n当当p=ap=a后,有下列等价关系存在:后,有下列等价关系存在:n(1)(1)数组元素的表示:数组元素的表示:n 下标法:下标法:pi pi 、aiain 间接引用法:间接引用法:* *(p+i) (p+i) 、* *(a+i)(a+i)n(2)(2)数组元素地址的表示数组元素地址的表示: :n 指针表达式法:指针表达式法:p+ip+i、a+i a+i n 元素取地址法:元素取地址法:&pi&pi、&ai&ain程序程序
35、5.5:5.5:用一级指针访问一维数组元素示例用一级指针访问一维数组元素示例 a0a1a2a3a3a4a413ff58app0p1p2p3p3p4p413ff5813ff5cp0p1p1p2p2n移动下标与移动指针访问数组的元素例示移动下标与移动指针访问数组的元素例示: :n程序程序5.8 5.8 请将一个初值分别为请将一个初值分别为1 1、2 2、3 3、4 4、5 5、7 7、8 8、9 9、1010的整的整形数组形数组逆置存放,并输出逆置后数组元素。逆置存放,并输出逆置后数组元素。 n分析:逆置数组,即从两边向中间对应位置的元素两两分析:逆置数组,即从两边向中间对应位置的元素两两互换互换
36、。n方法一:方法一:采用移动下标法采用移动下标法, ,用用i i和和j j分别指示待交换的两分别指示待交换的两个元素的下标,个元素的下标,i i从从0 0开始递增,开始递增,j j从从9 9开始递减,循环条开始递减,循环条件为件为ijij。n方法二:方法二:采用移动指针法,设两个指针采用移动指针法,设两个指针p p和和q q分别指向第分别指向第一个元素和最后一个元素,一个元素和最后一个元素,交换对应的交换对应的* *p p和和* *q q,然后,然后p+p+同时同时q-q-,循环条件为循环条件为pqpq。n程序程序5.8 5.8 方法一核心代码方法一核心代码nfor (i=0,j=9;ij;i
37、+,j-) nntemp=ai;nai=aj;naj=temp;nn等效于等效于:(只用只用 i 控制下标控制下标)nfor (i=0;i10/2;i+) ntemp=ai;nai=a10-1-i;na10-1-i=temp;n n程序程序5.8 5.8 方法二核心代码方法二核心代码nfor (p=a,q=a+9;pq;p+,q-)nntemp=*p;n*p=*q;n*q=temp;nn等效于等效于:(只用只用 p 控制指针变化控制指针变化)nfor (p=a;pa+10/2;p+)ntemp=*p;n*p=*(a+10-1-(p-a);n*(a+10-1-(p-a)=temp;n n程序程序5.9 5.9 从键盘上输入从键盘上输入n(1n10)n(1n10)个整数作为数组个整数作为数组a a的元素值,的元素值,再读入一个待查找的整数再读入一个待查找的整数x x,在,在a a数组中查找数组中查找x x,如果存在
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2024年初级审计师考试手册分享试题及答案
- 2025年建造师招投标试题及答案
- 中级审计师考试冲刺攻略试题及答案
- 一级建造师考试费解知识点解析试题及答案
- 无人机驾驶员考试的注意事项试题及答案
- 2025年入团考试知识更新试题及答案
- 2024高级会计考试常见试题及答案解析
- 初学者攻略2024年高级会计试题及答案
- 全景揭秘中级审计师考试试题及答案
- 中级审计师的职场发展与试题及答案的连接
- 2025年标准租房合同范本
- 三元空间下个人化IP综艺《灿烂的花园》叙事与价值研究
- 2025届安徽省池州市普通高中高三教学质量统一监测政治试卷含、答案
- 《汽车博览会》名师课件2
- 学校食堂“三同三公开”制度实施方案
- 海南2025年海南热带海洋学院招聘113人笔试历年参考题库附带答案详解
- 2024-2025学年人教版(2024)七年级英语下册Unit 6 rain or shine Section A 2a-2e 教案
- 比较文学形象学-狄泽林克
- 商业地产运营管理规章制度
- 2018中国痴呆与认知障碍诊治指南(九)中国记忆障碍门诊建立规范(全文版)
- 脱髓鞘病淋巴瘤
评论
0/150
提交评论