




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
1、单片机C言语开发技术第六章 数组与指针内容概述内容概述v数组是一种构造类型的数据,通常用来处置具有一样属性的一批数据。本章主要引见一维数组、二维数组、多维数组以及字符数组的定义、初始化、援用及运用。vC51言语还提供了构造类型的数据,它们有:数组类型、构造体类型、共用体类型。构造类型数据是由根本类型数据按一定规那么组成的,因此有的书称它们为“导出类型。6.1 一维数组6.1.1 一维数组的定义一维数组的定义方式为:类型阐明符 数组名常量表达式; 例如:int a10;它表示数组名为a,此数组有10个元素。v阐明:v1) 数组名的定名规那么和变量名一样,遵照标识符定名规那么;v2) 数组名后是用
2、方括弧括起来的常量表达式,不能用圆括弧,下面用法不对:int a(10);v3) 常量表达式表示元素的个数,即数组长度。例如,在a10中,10表示a数组有10个元素,下标从0开场,这10个元素是,a0,a1,a2,a3,a4,a5,a6,a7,a8,a9。留意不能运用数组元素a10;v(4) 常量表达式中可以包括常量和符号常量,不能包含变量。也就是说,C51不允许对数组的大小作动态定义,即数组的大小不依赖于程序运转过程中变量的值。例如,下面这样定义数组是不行的: int n;scanf(%d,&n);int an;6.1.2一维数组元素的援用 数组必需先定义,后运用。C51言语规定只能
3、逐个援用数组元素而不能一次援用整个数组。 数组元素的表示方式为:数组名下标 下标可以是整型常量或整型表达式。例如: a0=a5+a7-a2*3 例6-1-1 数组元素的援用 #include#includervoid main(void ) int i,a10; #ifndef MONITOR51 /* 需求串口输出时请作如下设置*/ SCON = 0 x50; /* 方式 1, 允许接纳 */ TMOD |= 0 x20; /* TMOD:定时器1方式2 */ TH1 = 221; /* 1200bps 16MHz */ TR1 = 1; /* 启动定时器1 */ TI = 1; /*Kei
4、l C自带的puchar()函数需求设置TI1*/ #endif for (i=0; i=0; i-) printf(%d ,ai); 6.1.3 一维数组的初始化对数组元素的初始化可以用以下方法实现:1)在定义数组时对数组元素赋以初值。例如:int a10=0,1,2,3,4,5,6,7,8,9; 2) 可以只给一部分元素赋值。例如:int a10=0,1,2,3,4; 定义a数组有10个元素,但花括弧内只提供5个初值,这表示只给前面5个元素赋初值,后5个元素值为0。3) 假设想使一个数组中全部元素值为0,可以写成int a10=0,0,0,0,0,0,0,0,0,0;不能写成int a10
5、=0*10;4) 在对全部数组元素赋初值时,可以不指定数组长度。例如:int a5=1,2,3,4,5;可以写成int a=1,2,3,4,56.1.4 一维数组运用举例一维数组运用举例v例6-1-2 知某课程的平常、实习、检验和期末成果,求该课程的总评成果。其中平常、实习、检验和期末分别占10、20、20、50。v#includev#include vvoid main(void)v int i=1,j;v char con_key=x20; / x20 空格键的ASCII码v float score5,ratio4=0.1,0.2,0.2,0.5; /*定义成果、比例系数数组*/v#ifn
6、def MONITOR51 /* 需求从串口1输出时请作如下设置*/v SCON = 0 x50; /* 方式 1, 允许接纳 */v TMOD |= 0 x20; /* TMOD:定时器1方式2 */v TH1 = 221; /* 1200bps 16MHz */v TR1 = 1; /* 启动定时器1 */v TI = 1; /*Keil C自带的puchar()函数需求设置TI1*/v#endifv while(con_key=x20) printf(输入第%2d个学生的成果n, i+); printf(平常 实习 检验 期末成果n); score4=0;/* score4:存储总评成果
7、*/ for(j=0; j4; j+) scanf(%f,&scorej); score4 += scorej * ratioj; printf(总评成果为:%6.1fn, score4); getchar(); 6.2 二维数组6.2.1 二维数组的定义 二维数组定义的普通方式为 类型阐明符 数组名常量表达式常量表达式 例如: float a34,b510;不能写成 float a3,4,b5,10;6.2.2二维数组元素的援用 援用二2维数组元素的方式为:数组名行下标表达式列下标表达式1“行下标表达式和“列下标表达式,都应是整型表达式或符号常量。2“行下标表达式和“列下标表达式的值
8、,都应在已定义数组大小的范围内。假设有数组x34,那么可用的行下标范围为02,列下标范围为03。3对根本数据类型的变量所能进展的操作,也都适宜于一样数据类型的二维数组元素。6.2.3 二维数组的初始化1按行赋初值 数据类型 数组名行常量表达式列常量表达式第0行初值表,第1行初值表,最后1行初值表;赋值规那么:将第0行初值表中的数据,依次赋给第0行中各元素;将“第1行初值表中的数据,依次赋给第1行各元素;以此类推。2按二维数组在内存中的陈列顺序给各元素赋初值数据类型 数组名行常量表达式列常量表达式初值表;赋值规那么:按二维数组在内存中的陈列顺序,将初值表中的数据,依次赋给各元素。假设对全部元素都
9、赋初值,那么“行数可以省略。留意:只能省略“行数。 6.2.4 二维数组运用举例例6-2-1 有M个学生,学习N门课程,知一切学生的各科成果,编程:分别求每个学生的平均成果和每门课程的平均成果。 #define NUM_std 5/*定义符号常量人数为5*/#define NUM_course 4/*定义符号常量课程为4*/#include main() int i,j; static xdata float scoreNUM_std+1NUM_course+1=78,85,83,65, 88,91,89,93, 72,65,54,75,86,88,75,60, 69,60,50,72; fo
10、r(i=0;iNUM_std;i+) for(j=0;jNUM_course;j+) scoreiNUM_course += scoreij;/*求第i个人的总成果*/ scoreNUM_stdj += scoreij;/*求第j门课的总成果*/ scoreiNUM_course /= NUM_course;/*求第i个人的平均成果*/ for(j=0;jNUM_course;j+) scoreNUM_stdj /= NUM_std; /*求第求第j门课的平均成果门课的平均成果*/ /*输出表头输出表头*/ printf(学生编号学生编号 课程课程1 课程课程2 课程课程3 课程课程4 个人平
11、均个人平均n); /*输出每个学生的各科成果和平均成果输出每个学生的各科成果和平均成果*/for(i=0;iNUM_std;i+) printf(学生学生%dt,i+1); for(j=0;jNUM_course+1;j+) printf(%6.1ft,scoreij); printf(n); /*输出输出1条短划线条短划线*/ for(j=0;j8*(NUM_course+2);j+) printf(-); printf(n课程平均课程平均); /*输出每门课程的平均成果输出每门课程的平均成果*/ for(j=0;jNUM_course;j+) printf(%6.1ft,scoreNUM_
12、stdj); printf(n); 6.3字符数组v用来存放字符量的数组称为字符数组。v字符数组类型阐明的方式与前面引见的数值数组一样。v例如:vchar c10; vchar c510;/即为二维字符数组。字符数组也允许在类型阐明时作初始化赋值。vstatic char c=c, ,p,r,o,g,r,a,m;/ 当对全体元素赋初值时也可以省去长度阐明 v例6-3-1 定义一个二维数组,在放字符串“BASIC、“DBASE,并输出。v#includevvoid main(void)vvint i,j;vchar a5=B,A,S,I,C,d,B,A,S,E;vfor(i=0;i=1;i+)v
13、 v for(j=0;j=4;j+)v printf(%c,aij);v printf(n);v vv字符串在言语中没有专门的字符串变量, 通常用一个字符数组来存放一个字符串。v字符串总是以0作为串的终了符。因此当把一个字符串存入一个数组时, 也把终了符0存入数组,并以此作为该字符串能否终了的标志。 v有了0标志后,就不用再用字符数组的长度来判别字符串的长度了。vC51言语允许用字符串的方式对数组作初始化赋值。例如: vstatic char c=c, ,p,r,o,g,r,a,m; v可写为:static char c=C program; v或去掉写为:sratic char c=C pr
14、ogram;v用字符串方式赋值比用字符逐个赋值要多占一个字节, 用于存放字符串终了标志0。 v除了上述用字符串赋初值的方法外,还可用printf函数和scanf函数一次性输出输入一个字符数组中的字符串, 而不用运用循环语句逐个地输入输出每个字符。vvoid main() static char c=BASICndBASE; printf(%sn,c); v留意在本例的printf函数中,运用的格式字符串为“%s, 表示输出的是一个字符串。而在输出表列中给出数组名那么可。 不能写为: printf(%s,c);6.4 多维数组 v多维数组的普通阐明格式是: v 类型 数组名第n维长度第n-1维长
15、度.第1维长度;v例如: v int m32; /*定义一个整数型的二维数组*/ v char c223; /*定义一个字符型的三维数组*/ v数组m32共有3*2=6个元素, 顺序为: v m00, m01, m10, m11, m20, m21; v数组c223共有2*2*3=12个元素, 顺序为: v c000, c001, c002, v c010, c011, c012, v c100, c101, c102, v c110, c111, c112, v数组占用的内存空间(即字节数)的计算式为: v 字节数=第1维长度*第2维长度*.*第n维长度*该数组数据类型占用的字节数 vC51
16、中数组进展初始化有下述规那么: v 1) 数组的每一行初始化赋值用“并用“,分开, 总的再加一对“括起来, 最后以;表示终了。 v 2) 多维数组存储是延续的, 因此可以用一维数组初始化的方法来初始化多维数组。v 3) 对数组初始化时, 假设初值表中的数据个数比数组元素少, 那么缺乏的数组元素用0来填补。 6.5 指针6.51 指针和地址 6.5.1.1 指针变量的定义C51言语中, 对于变量的访问方式之一, 就是先求出变量的地址, 然后再经过地址对它进展访问, 这就是这里所要论述的指针及其指针变量。所谓变量的指针, 实践上指变量的地址 变量的地址虽然在方式上好象类似于整数, 但在概念上不同于
17、以前引见过的整数, 它属于一种新的数据类型, 即指针类型。C51中, 普通用“指针来指明这样一个表达式&x的类型, 而用“地址作为它的值, 也就是说, 假设x为一整型变量, 那么表达式&x的类型是指向整数的指针, 而它的值是变量x的地址。 v同样, 假设 double d;那么&d的类型是指向双精度数d的指针, 而&d的值是双精度变量d的地址。所以, 指针和地址是用来表达一个对象的两个方面。v&x、&d的类型是不同的, 一个是指向整型变量x的指针,而另一个那么是指向双精度变量d的指针。v指针变量的普通定义为:v类型标识符 *标识符; v其中标识符
18、是指针变量的名字, 标识符前加了“*号, 表示该变量是指针变量v“类型标识符表示该指针变量所指向的变量的类型。v一个指针变量只能指向同一种类型的变量v定义一个指针类型的变量。vint *ip;v首先阐明了它是一指针类型的变量, 留意在定义中不要漏写符号“*, 否那么它为普通的整型变量了。v另外, 在定义中的int 表示该指针变量为指向整型数的指针类型的变量, 有时也可称ip为指向整数的指针。vip是一个变量, 它专门存放整型变量的地址。v指针变量在定义中允许带初始化项。如: v int i, *ip=&i;v。C51中规定, 当指针值为零时, 指针不指向任何有效数据, 有时也称指针为空
19、指 6.5.1.2 指针变量的援用 既然在指针变量中只能存放地址, 因此, 在运用中不要将一个整数赋给一指针变量. 下面的赋值是不合法的: int *ip; ip=100;假设:int i=200, x;int *ip;可以把i的地址赋给ip: ip=&i; 此时指针变量ip指向整型变量i, 假设变量i的地址为1800, 这个赋值可笼统了解为以下图所示的联络。 ip i 1800 200 图5-1-1 给指针变量赋值v以后我们便可以经过指针变量ip间接访问变量i, 例如: vx=*ip; v运算符*访问以ip为地址的存贮区域, 而ip中存放的是变量i的地址, 因此, *ip访问的是地址
20、为1800的存贮区域(由于是整数, 实践上是从1800开场的两个字节),它就是i所占用的存贮区域, 所以上面的赋值表达式等价于vx=i;v另外, 指针变量和普通变量一样, 存放在它们之中的值是可以改动的, 也就是说可以改动它们的指向, 假设v int i, j, *p1, *p2; i=a; v j=b; p1=&i; p2=&j; v那么建立如图5-1-2所示的联络:v p1 i a p2 i b 图5-1-2 赋值运算结果 v这时赋值表达式:vp2=p1;v就使p2与p1指向同一对象i, 此时*p2就等价于i, 而不是j, 图5-1-2就变成图5-1-3所示: v p1 i
21、 a p2 j b 图5-1-3 p2=p1时的情形 v假设执行如下表达式: *p2=*p1; v那么表示把p1指向的内容赋给p2所指的区域, 此时图5-1-2就变成图5-1-4所示:v p1 i a p2 j a v 图5-1-4 *p2=*p1时的情形 由于指针是变量, 我们可以经过改动它们的指向, 以间接访问不同的变量, 这给程序员带来灵敏性, 也使程序代码编写得更为简约和有效。 指针变量可出如今表达式中, 设:int x, y *px=&x; 指针变量px指向整数x, 那么*px可出如今x能出现的任何地方。例如:y=*px+5; /* 表示把x的内容加5并赋给y */ y=+*
22、px; /* px的内容加上1之后赋给y ,+*px相当于+(px) */ y=*px+; /* 相当于y=*px; px+ */ 6.5.1.3 地址运算 指针允许的运算方式有:1) 指针在一定条件下, 可进展比较, 这里所说的一定条件, 是指两个指针指向同一个对象才有意义, 例如两个指针变量p, q指向同一数组, 那么, =,=, =等关系运算符都能正常进展。假设p=q为真, 那么表示p, q指向数组的同一元素; 假设pq为真, 那么表示p所指向的数组元素在q所指向的数组元素之前(对于指向数组元素的指针在下面将作详细讨论)。2) 指针和整数可进展加、减运算。设p是指向某一数组元素的指针,
23、开场时指向数组的第0号元素, 设n为一整数, 那么: p+n 就表示指向数组的第n号元素(下标为n的元素)。 不论指针变量指向何种数据类型, 指针和整数进展加、减运算时, 编译程序总根据所指对象的数据长度对n放大 在普通微机上, char放大因子为1, int、short放大因子为2, long和float放大因子为4, double放大因子为8。3) 两个指针变量在一定条件下, 可进展减法运算。设p, q指向同一数组, 那么p-q的绝对值表示p所指对象与q所指对象之间的元素个数。 其相减的结果遵守对象类型的字节长度进展减少的规那么。 6.5.2 指针和数组 v指针和数组有着亲密的关系, 任何
24、能由数组下标完成的操作也都可用指针来实现, 但程序中运用指针可使代码更紧凑、更灵敏。6.5.2.1. 指向数组元素的指针 定义一个整型数组和一个指向整型的指针变量: int a10, *p; 和前面引见过的方法一样, 可以使整型指针p指向数组中任何一个元素, 假定给出赋值运算 p=&a0; 此时, p指向数组中的第0号元素, 即a0, 指针变量p中包含了数组元素a0 的地址, 由于数组元素在内存中是延续存放的, 因此, 我们就可以经过指针变量p及其有关运算间接访问数组中的任何一个元素。 C51中, 数组名是数组的第0号元素的地址, 因此下面两个语句是等价的: p=&a0; p=
25、a; 根据地址运算规那么, a+1为a1的地址, a+i就为ai的地址。 下面我们用指针给出数组元素的地址和内容的几种表示方式。1) p+i和a+i均表示ai的地址, 或者讲, 它们均指向数组第i号元素, 即指向ai。2) *(p+i)和*(a+i)都表示p+i和a+i所指对象的内容, 即为ai。3) 指向数组元素的指针, 也可以表示成数组的方式, 也就是说, 它允许指针变量带下标, 如pi与*(p+i)等价。假假设:p=a+5;那么p2就相当于*(p+2), 由于p指向a5, 所以p2就相当于a7。而p-3就相当于*(p-3), 它表示a2。 6.5.2.2. 指向二维数组的指针1 二维数组
26、元素的地址 为了阐明问题, 我们定义以下二维数组: int a34=0,1,2,3, 4,5,6,7, 8,9,10,11; a为二维数组名, 此数组有3行4列, 共12个元素。但也可这样来了解, 数组a由三个元素组成: a0, a1, a2,每个元素又是一个一维数组, 且都含有4个元素 (相当于4列), 例如, a0所代表的一维数组所包含的 4 个元素为a00, a01, a02, a03。如图5-1-5所示。 但从二维数组的角度来看, a代表二维数组的首地址, 当然也可看成是二维数组第0行的首地址。a+1就代表第1行的首地址, a+2就代表第2行的首地址。假设此二维数组的首地址为1000,
27、 由于第0行有4个整型元素, 所以a+1为1008, a+2也就为1016,如图5-1-6所示 。 v既然我们把a0, a1, a2看成是一维数组名, 可以以为它们分别代表它们所对应的数组的首地址.a0代表第 0 行中第 0 列元素的地址,即&a00, a1是第1行中第0列元素的地址, 即&a10, 根据地址运算规那么, a0+1即代表第0行第1列元素的地址, 即&a01, 普通而言, ai+j即代表第i行第j列元素的地址, 即&aij。 另外, 在二维数组中, 我们还可用指针的方式来表示各元素的地址。如前所述, a0与*(a+0)等价, a1与*(a+1)等价
28、, 因此ai+j就与*(a+i)+j等价, 它表示数组元素aij的地址。 因此, 二维数组元素aij可表示成*(ai+j)或*(*(a+i)+j), 它们都与aij等价, 或者还可写成(*(a+i)j。 另外, 要补充阐明一下, 假设他编写一个程序输出打印a和*a, 他可发现它们的值是一样的, 这是为什么呢? 我们可这样来了解: 首先, 为了阐明问题, 我们把二维数组人为地看成由三个数组元素a0, a1, a2组成, 将a0, a1, a2看成是数组名它们又分别是由4个元素组成的一维数组。因此, a表示数组第 0行的地址, 而*a即为a0, 它是数组名, 当然还是地址, 它就是数组第0 行第0
29、列元素的地址。 2 指向一个由n个元素所组成的数组指针v在C51中, 可定义如下的指针变量:vint (*p)3;v指针p为指向一个由3个元素所组成的整型数组指针。v在定义中, 圆括号是不能少的, 否那么它是指针数组。v这种数组的指针不同于前面引见的整型指针, 当整型指针指向一个整型数组的元素时, 进展指针(地址)加1运算,表示指向数组的下一个元素, 此时地址值添加了2(由于放大因子为2), 而如上所定义的指向一个由3个元素组成的数组指针, 进展地址加1运算时, 其地址值添加了6(放大因子为23=6), 这种数组指针在C51中用得较少, 但在处置二维数组时, 还是很方便的。例如: vint a
30、34, (*p)4;vp=a;v开场时p指向二维数组第0行, 当进展p+1运算时, 根据地址运算规那么, 此时放大因子为42=8, 所以此时正好指向二维数组的第1行。v和二维数组元素地址计算的规那么一样, *p+1指向a01, *(p+i)+j那么指向数组元素aij。例6-5-1 利用指针输出二维数组中的元素。#includeint a3 4= 1,3,5,7,9,11,13,15, 17,19,21,23 ; main() int i,(*b)4; b=a+1; /* b指向二维数组的第1行, 此时*b0或 *b是a10 */ for(i=1;i=4;b=b0+2,i+)/* 修正b的指向,
31、 每次添加2 */ printf(%d t,*b0); printf( n); for (i=0; i2; i+) b=a+i; /* 修正b的指向, 每次跳过二维数组的一行 */ printf(%d t,*(bi+1); printf ( n); 程序运转结果如下: 6.5.3 字符指针字符指针 在程序中如出现字符串常量在程序中如出现字符串常量,C51编译程编译程序就给字符串常量按排一存贮区域序就给字符串常量按排一存贮区域, 这个区域这个区域是静态的是静态的, 在整个程序运转的过程中一直占用。在整个程序运转的过程中一直占用。 字符串常量的长度是指该字符串的字符字符串常量的长度是指该字符串的字
32、符个数个数, 但在按排存贮区域时但在按排存贮区域时, C 编译程序还自编译程序还自动给该字符串序列的末尾加上一个空字符动给该字符串序列的末尾加上一个空字符0, 用来标志字符串的终了。用来标志字符串的终了。 因此一个字符串常量所占的存贮区域的因此一个字符串常量所占的存贮区域的字节数总比它的字符个数多一个字节。字节数总比它的字符个数多一个字节。C51中操作一个字符串常量的方法1) 把字符串常量存放在一个字符数组之中, 例如: char s=a string; 数组s共有9个元素所组成, 其中s8中的内容是0。实践上, 在字符数组定义的过程中, 编译程序直接把字符串复写到数组中, 即对数组s初始化。
33、2) 用字符指针指向字符串, 然后经过字符指针来访问字符串存贮区域。当字符串常量在表达式中出现时, 根据数组的类型转换规那么, 它被转换成字符指针。因此, 假设我们定义了一字符指针cp:char *cp;于是可用:cp=a string; v使cp指向字符串常量中的第0号字符a, 如图5-1-8所示。 v cp a s t r i n g 0 图5-1-8 指针指向字符串v以后我们可经过cp来访问这一存贮区域, 如*cp或cp0就是字符a, 而cpi或 *(cp+i)就相当于字符串的第i号字符, 但企图经过指针来修正字符串常量的行为是没有意义的。 6.5.4 指针数组指针数组的定义格式为: 类型标识 *数组名整型常量表达式;例如: int *a10;v指针数组和普通数组一样, 允许指针数组在定义时初始化。v指针数组 的每个元素是指针变量, 它只能存放地址。v所以对指向字符串的指针数组在阐明赋初值时, 是把存放字符串的首地址赋给指针数
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 仓储管理中的供应商关系管理试题及答案
- 保安理论知识培训课件
- 2024年CPSM学习与之相伴的工具试题及答案
- 精准定位CPSM考试难点试题及答案
- 供应链管理中采购绩效的评价方法试题及答案
- 探讨CPSM考试的未来方向试题及答案
- 信贷法律风险防控课件
- 国际物流师未来发展趋势考题解析试题及答案
- 电商设计师关系维护试题及答案
- 2024年CPMM学习交流试题及答案
- 《新媒体广告》课件3伦理与法规
- 中国标准色卡样本
- FMEA潜在失效模式及后果分析(第五版)培训课件
- 专业工程分包备案表
- 回弹法检测混凝土抗压强度技术规程
- 下穿渝合高速施工方案
- 重点时段及节假日前安全检查表
- 引水隧洞施工中通风计算
- 苏教版四年级数学下册《常见的数量关系》优秀PPT课件
- 个人外汇管理办法实施问答(一二三四期)(共5页)
- ▲封头重量计算
评论
0/150
提交评论