二.教学讲点
1.一维数组与指针
(1)在C语言中,数组是占用一串连续的存储单元。数组中每个元素都可以看作一个变量,因此每个数组元素都有一个地址。 那么:int *p,a[5]={1,2,3,4,5};
指针p的基类型是int,数组a的各个元素也是int类型的。我们用p=&a[0],将指针p指向数据元素a[0]。由于数组元素在内存中是连续的,因此我们可以通过移动指针p来访问数组中的每一个元素。
(2)C语言规定数组名代表数组在内存中的起始地址,即可以用a表示数组a的首地址。因此p=a是让指针p指向数组a的起始地址。
(3)a是一个地址常量,它永远指向a数组的首地址。因此我们不能对a进行重新赋值。如:a=&I,a++都是错的。
2. 通过指针引用一维数组元素
(1)通过指针引用数组元素
int *p,a[5]={1,2,3,4,5};
int *p,a[5]={1,2,3,4,5};
p=&a[0]; p=a;
指针变量p指向数组元素a[0], 指针变量p指向数组元素a[0], 因此可以用间接访问运算符“*”
因此可以用间接访问运算符“*”来引用变量a[0]。如:*p=10;是来引用变量a[0]。
如:*p=10;是 对指针的存储空间赋值,即a[0]=10 原来a[0]=1,那么通过指针赋值现在 变成了10.
(2)通过数组的首地址引用数组元素 int a[5];
由于a是数组的首地址,我们把a当作一个指针常量。因此*a等价于a[0]; *(a+1)等价于a[0]。a等价于&a[0]。
(3)用带下标的指针变量引用一维数组元素
int *p,a[5]={1,2,3,4,5}; p=a;
p[0]来表示a[0],p[1]来表示a[1]……
(4)对数组元素a[i]等价的引用方法:
a[i]; p[i]; *(a+i); *(p+i).
(5)补充
若指针变量P指向了一维数组a的首地址,即:int a[10]; int *p=a;
则有下面的等价关系:
(1)a+i等价于p+i,都是&a[i]。
(2)*(a+i) 等价于*(p+i) 都与a[i]相同 (3)a[i]等价于p[i]
(4)p++、++p、p+=1、p=p+1作用都是让p指向下一个元素。p--、--p、p-=1、p=p-1作用都是让p指向前一个元素。
(5)*p++与*(p++)等价,都是得到p当前所指向的元素的值,并让p指向下一个元素。*p--与*(p--)等价,都是得到p当前所指向的元素的值,并让p指向前个元素。
(6)*++p与*(++p)等价,都是先让p指向下一
个元素,再取出重新指向的元素。*--p与*(--p)
等价,都是先让p指向前一个元素,再取出重新指向的元素。 (7)(*p)++、++(*p)、++*p的作用都是让p当前所指的元素值增加1。(*p)--、--(*p)、--*p的作用都是让p当前所指的元素值减小1。
3.指向多维数组的指针和指针变量
int a[3][4];
3.1.列指针:加1跳过一个元素的指针。 (如:一维数组名)
3.2.行指针:加1跳过一行的指针。 (如:二维数组名)
3.3.对列指针进行一次指针(下标)运算得到的是元素。 例如:int a[5]={1,2,3,4,5},*p=a;
则a[3]等价于p[3]等价于*(p+3),都得到元素a[3]的值4。
3.4.对行指针进行一次指针(下标)运算得到的列指针(即元素的地址),而不是元素。若要通过行指针引用元素,必须进行两次指针运算或下标运算。 若a是一个二维数组,则有:
a+i是行指针,指向行号为i的一整行。
*(a+i)和a[i]等价,都是一个列指针,指向的是元素。都表示行号为i的最前面元素的地址,即&a[i][0]。
*(a+i)+j和a[i]+j等价,即&a[i][j]。 *(*(a+i)+j)、*(a[i]+j)、(*(a+i))[j] 和a[i][j]相同。 例.若有以下定义: float a[2][3];
则对a数组元素非法引用的是( )。
A.*(a[0]+2) B.*(a+1)[2]
C.a[0][0] D.*(a[1]+2) E.*(a[1]+3) F.(*(a+1))[2]
a[0][0] a[0][1] a[0][2] a[0][3]
a[1][0] a[1][1] a[1][2] a[1][3]
a[2][0] a[2][1] a[2][2] a[2][3]
a a+1 a+2
4.指向多维数组元素的指针变量
指向多维数组元素的指针变量的定义和引用与指向普通变量的指针变量的定义和引用的方法一样。 例如:int a[3][4]; int *p=&a[1][2]; 则:
表达式 所指元素 P+1 a[1][3] P+2 a[2][0] P+4 a[2][2]
常用于取二维数组a元素地址的方式:&a[i][j] 、a[i]+j、*(a+i)+j
5.指向由m个元素组成的一维数组的指针变量
它是一个行指针,对它加1要跳过m个元素。
而指向一维数组的指针变量是一个列指针。对它加1跳过1个元素。 定义格式:
基类型 (*指针变量名)[m];
定义后该指针变量与具有m列的二维数组名具有相同的性质,即该指针变量可以指向一个具有m列的二维数组。通过该指针变量名引用二维数组元素时,引用方式与通过二维数组名的引用方式一样。 int a[5][7]; int (*p)[7]; p=a;
此时p[0][0]与a[0][0]对应 p[4][3]与a[4][3] 对应 char b[10][80]; char (*r)[80]; r=b+5;
例1.请分析r[0][0]和r[2][3]分别对应的元素是 和 。
例2.若有int t[3][2];能正确表示t数组元素地址的表达式是( )。 A.&t[3][0] B.t[3] C.t[1] D.*t[2]
6.指针数组
定义格式:
类型名 *数组名[常量表达式];
例如:
int a[10];普通数组 int *a[10];指针数组
int (*a)[10];指向由10个元素组成的一维数组的指针变量 int (*a)();指向函数的指针变量 int *a()返回指针值的函数 { … } 注意:
1.指针数组的每一个元素都是指针类型,即它的每一个元素相当于一个指针变量。
2.指针数组的数组名是一个行指针。 以下程序的输出结果是 main()
{char ch[3][4]={“321”,”654”,”212”},*q[3]; int i;
for(i=0;i<3;i++) q[i]=ch[i];
for(i=0;i<3;i++) printf(“%s”,q[i]); }
有下列语句
float (*a)[6],*b[6];
则sizeof(a)、sizeof(b)的值各是?结果:4,24 int a; int a[10]; int *a; int *a[10];
三.试题分析
1.2008年4月试题分析
(9)以下程序段的定义语句中,x[1]的初值是【9】,程序运行后输出的内容是【10】。 #include<stdio.h> main()
{ int x[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16},*p[4],i; for(i=0;i<4;i++) { p[i]=&x[2*i+1]; printf(“%d ”,p[i][0]); }
printf(“\n”); }
(11)以下程序的输出结果是【12】。 #include<stdio.h> main()
{ int a[5]={2,4,6,8,10}, *p; p=a; p++;
printf(“%d”,*p);
}
2.2007年9月试题分析
(31)若有定义语句:int a[3][6]; ,按在内存中的存放顺序,a数组的第10个元素是 A)a[0][4] B)a[1][3] C)a[0][3] D)a[1][4]
(33)若有定义语句:int a[2][3],*p[3]; ,则以下语句中正确的是 A)p=a; B)p[0]=a; C)p[0]=&a[1][2]; D)p[1]=&a; (34)有以下程序 #include <stdio.h> void fun(int *a, int n) /* fun函数的功能是将a所指数组元素从大到小排序 */ { int t, i, j; for (i=0; i<n-1;i++) for (j=i+1; j<n; j++) if (a[i]<a[j]) { t=a[i]; a[i]=a[j]; a[j]=t; } } main() { int c[10]={1,2,3,4,5,6,7,8,9,0},i; fun(c+4, 6); for (i=0;i<10; i++) printf("%d,", c[i]); printf("\n"); }
程序的运行结果是 A)1,2,3,4,5,6,7,8,9,0, B)0,9,8,7,6,5,1,2,3,4, C)0,9,8,7,6,5,4,3,2,1, D)1,2,3,4,9,8,7,6,5,0,
3.2007年4月试题分析
(36) 有以下程序 void f(int *q) {int i=0;
for( ; i<5;i++)(*q)++; }
main()
{int a[5]={1,2,3,4,5},i; f(a);
for(i=0;i<5;i++)printf(“%d,”,a[i]); }
程序运行后的输出结果是( )
A)2,2,3,4,5, B)6,2,3,4,5, C)1,2,3,4,5, D) 2,3,4,5,6,
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。