10数组与指针
- 格式:doc
- 大小:72.50 KB
- 文档页数:8
数组与指针一个变量有地址,一个数组包含若干元素,每个数组元素都在内存中占用存储单元,它们都有相应的地址,所谓数组元素的指针就是数组元素的地址。
引用数组元素可以用下标(如a[3]),也可以用指针法,即通过指向数组元素的指针找到所需的元素。
使用指针法能使目标程序质量高(占内存少,运行速度快)。
一维数组和指针1.指向数组元素的指针例:int a[10]; /*定义a为包含10个整型数据的数组*/int *p; /*定义p为指向整型变量的指针变量*/p=&a[0]; 把a[0]元素的地址赋给指针变量p。
也就是说,p指向a数组的第0号元素。
C 语言规定数组名代表数组中第一个元素(即序号为0的元素)的地址,因此下面两个语句等价:p=&a[0]; 与p=a 等价。
注意:数组名不代表整个数组,“p=a”的作用把a数组的首元素的地址赋给指针变量p,而不是把数组a各元素的值赋给p.在定义指针变量时,可以对它赋初值:int *p=&a[0];或int *p=a;2.通过数组的首地址引用数组元素由以上可知:a是a数组元素的首地址,a(即:a+0)的值就等于&a[0];则a+1的值,就等于&a[1], a+2就等于&a[2],……a+9就等于&a[9]这里,可以通过”取地址运算符*”来引用地址所在的存储单元,因此,对于数组元素a[0],可以通过表达式*&a[0]来引用,也可以用*(a+0)来引用,对此也可以写成:*a;而对于数组元素a[1],可以用表达式*&a[1]来引用,也可以用*(a+1)来引用……对于a[9]可以用*&a[9]来引用,也可以用*(a+9)来引用。
因此可以通过以下的语句输出a数组元素中的值:for(k=0;k<10;k++) printf(“%4d”,*(a+k));就相当于:for(k=0;k<10;k++) printf(“%4d”,a[k]);3.通过指针引用数组元素假如p已定义为一个指向整型数据的指针变量,并已给它赋了个整型数组元素的地址,使它指向某一个数组元素。
如果有以下定义语句:*p=1;表示对p当前所指向数组元素赋予一个值1。
按C的规定,如果指针变量p已指向数组元素中的一个元素,则p+1指向同一数组中的下一个元素(而不将p的值简单的加1)。
如果p的初值为&a[0],即p=a或p=&a[0],也可以使用“间接访问运算符*”,通过指针变量p不引用a数组中的元素,对于数组a[0],可以用表达式*(p+0)即*p来引用,a[1],也可以用表达式*(p+1)来引用,p+1的值就是数组元素a[1] 的地址……对于数组元素a[9]就可以用*(p+9)来引用。
所以当指针变量p指向a数组的起始地址时,可以通过以下语句输出a数组的元素:for(p=a,k=0;k<10;k++) printf(“%4d”,*(p+k);指针变量p可以移动:for(p=a,k=0;k<10;k++) { printf(“%4d”, *p), p++;}4用带下标的指针变量引用数组元素若有以下的定义:int *p , s[10],i ; p=s;可以用&s[i], s+i; 和p+i三种表达式来表示s[i]的地址,同时可以用s[i], *(s+i)和*(p+i)三种表达式来表示数组元素s[i];s[i]可以用表达式*(s+i)来表示,同理*(p+i)也应该可以用表达式p[i]的形式来表示。
因此,当p指向s数组的首地址时,表示数组元素s[i]的表达式有以下四种:(1)s[i] (2) *(s+i) (3)*(p+i) (4)p[i]这里,面s和p有着明显的区别,s是不可变的,而p中的地址却是可变的,因此,s++, s=p,p=&s 等运算都是不合法的,而p++,p=s,p=&s[i]则都是合法的表达式。
说明:(1)p+i和a+i就是a[i]的地址,或者说它们指向a数组的第i个元素,这里a代表数组元素的首地址,a+i也是地址。
(2)*(p+i)或*(a+i)是p+i或a+i所指向的数组元素,即a[i],即按数组首元素的地址加上相对位移量得到要找的元素的地址,然后找出该单元中的内容。
(3)指向数组的指针变量也可以带下标,如p[i]与*(p+i)等价。
注意:指针变量的运算:先使p指向数组a的首元素,则①p++或(p+=1),使p指向下一元素,即a[1]。
若再执行*p,取出下一个元素a[1]值。
②*p++,由于++和*同优先级,结合方向自右至左,因此它等价于*(p++)。
作用是先得到p指向的变量的值(即*p),然后再使p+1=>p.③*(p++)与*(++p)不同,前者是先取*p的值,然后使p加1。
后者是先使p加1 ,再取*p。
若p初值为a(即a[0]),输出*(p++)时,得a[0]的值;而输出*(++p),则得a[1]的值。
④(*p)++表示p所指向的元素值加1,即(a[0])++,如果a[0]=3;则(a[0])++的值为4。
函数与数组1用数组名作函数参数前面已经介绍过可用数组名和数组元素作函数参数。
数组元素实际上代表内存中的一个存储单元,和普通变量一样。
实参数组名代表该数组首元素的地址。
而形参是用来接收从实参传递过来的数组首元素的地址。
因此,形参应该是一个指针变量(只有指针能存放地址)。
例:编写程序,通过函数给数组输入若干大于等于0的整数,用负数作为输入结束的标志;调用函数输出该数组中的数据。
#define M 100void arrout(int *,int);arrin(int * );main(){ int s[M],k;k=arrin(s);arrout(s,k);}arrin(int *a){ int i,x;i=0;scanf("%d",&x);while(x>=0){ *(a+i)=x;i++;scanf("%d",&x);}return i;}void arrout(int *a,int n){ int i;for(i=0;i<n;i++)printf(((i+1)%5==0)?"%4d\n": "%4d",*(a+i));printf("\n");}当数组名作为实参时,对应的形参除了应该是指针外,形参还可以用另外两种形式。
对于函数调用arrin(s),对应的函数首部可以写成以下三种形式:(1)arrin(int *a)(2)arrin(int a[])(3)arrin(int a[M])但的C的编译程序都将把a处理成第一种的指针形式。
2数组元素地址作为实参当数组元素的地址作为实参时,因为是地址值,所以对应的形参也应当是基类型相同的指针变量。
例:编写函数,对于具有10个元素的char类型的数组,从下标为4的元素开始,全部设置为”*”号,保持前四个元素中的内容不变。
#define M 10#define B 4void setstar(char *,int);void arrout(char *,int);main(){ char c[M]={'A','B','C','D','E','F','G','H','I','J'};setstar(&c[4],M-B);arrout(c,M);getch();}void setstar(char *a,int n){ int i;for(i=0;i<n;i++)*(a+i)='*';}void arrout(char *a,int n){ int i;for(i=0;i<n;i++)printf("%c",a[i]);printf("\n");}setstar的首部还可以写成:setstar(char a[], int n) 或setstar(char a[M-B], int n)多维数组和指针1.二维数组a由若干个一维数组组成若有定义:int *p, a[3][4];a 是一个数组名,a数组包含3行,即3个元素:a[0],a[1],a[2]。
而每一元素又是一个一维数组,它包含4个元素。
可以有a[0][0],a[0][1]……来引用a[0]中的每一个元素,其它依次类推。
前面已介绍过:一维数组名是一个地址常量,其值为第一个元素的地址。
而在二维数组中,a[0],a[1],a[2]都是一维数组名,同样也代表一个不可变的地址常量,其值依次为二维数组的每行的第一个元素的地址。
指针变量p与a[i]相同,因此,p=a[i]是合法的。
对于a[i],可以写成:*(a+i),故也可以写成:p=*(a+i);2.二维数组名也是一个地址常量a 代表二维数组首元素的地址,现在的首元素不是一个整型变量,而是由4个整型元素所组成的一维数组,因此a代表的是首行(即第0行)的首地址,a+1 代表第1行的首地址,如果二维数组的首行地址为2000,,则a+1为2008。
因此a+1的含义是a[1]的地址。
a[0],a[1],a[2]既然是一维数组名,而C规定数组名代表数组元素首地址,因此a[0]代表一维数组第0列元素地址,即&a[0][0]。
a[1]的值是&a[1][0],a[2]的值是&a[2][0]。
那么,第0行第1列元素地址呢?3.二维数组元素的地址a[0]为一维数组名,该一维数组中第2个元素显然应该用a[0]+1来表示,此时,“1”代表1个列元素的字节数。
所以a[0]+0,a[0]+1,a[0]+2,a[0]+3,分别是a[0][0],a[0][1],a[0][2],a[0][3]元素的地址。
即:&a[0][0],&a[0][1],&a[0][2],&a[0][3]前面已经讲过a[0]和*(a+0)等价,a[1]和*(a+1)等价,a[i]和*(a+i)等价。
因此,a[0]+1和*(a+0)+1的值都是&a[0][1], a[1]+2和*(a+1)+2的值都是&a[1][2].若想得到a[0][1]的值,用地址法怎么表示呢?既然a[0]+1和*(a+0)+1是a[0][1]的地址,那么,*(a[0]+1)就是a[0][1]的值,同理,*(*(a+0)+1)或*(*a+1)也是a[0][1]的值。