目录
一、指向数组元素的指针变量的定义和赋值
数组指针是指数组的开始地址(首地址),数组元素的指针就是数组元素的地址。
a[3]=6;
下标法引用数组元素,也可以用指针引用数组元素。
int a[5]={5,6,7,8,9};
能引用的是0--4,只要是数组,那么数组元素的内存一定是紧挨着的,从首地址开始以数据类型所占字节进行叠加。
注意:数组名a代表的是数组的首地址,即数组名a等于数组中首元素的地址,a==&a[0]
定义指针变量时也可以给指针变量赋初值:int *p=a或*p=&a[0];
二、通过指针引用数组元素
- *p=19;等价于a[0]=19;
- p=p+1//增加了4,比如原来p=1000,p+1后p=1004,指针变量内保存的地址加上sizeof(类型)。
-
p+i 或者 a+i (i是数组元素的小标)
假如现在p指向数组首地址,a是数组名(代表数组首地址),那么p+i 或者 a+i 就是数组元素a[i]的地址,也就是她们指向了数组a的第i个元素。 相当于,p+3为&a[3]. 结论:p+i 或者 a+i 都是地址,可以赋给指针变量。 -
*(p+i)或者*(a+i):
从第3条可得,这两个是p+i a+i所指向的数组元素,也就是a[i],比如说*(p+2)或者*(a+2)就是a[2]. -
p[i]
p[i] == *(p+i) == a[i]
p[3]=19,则a[3]=19.
引用数组元素有很多方法:a[i];p[i];*(p+i);*(a+i);
- *p++:
优先级相同,并且都是从右到左的结合性,所以等价于*(p++)
p++为先用后加,所以*(p++)整个作用是:得到p指向的变量的值(*p),然后再使p指针自增,指向下一个数组元素。printf("%d\n",*p++);
先打印出a[0]的值,然后p指向了a[1]。 - *++p:
相当于*(++p),和第六不同,++p是先加后用,p会先自增1,;然后再去用p值。printf("%d\n",*++p);
p指向了a[1],打印a[1]的值。 - (*p)++:
表示p所指向的元素加1,如果p指向数组首地址,那就等价于a[0]++;实际上是数组元素值+1,不是指针+1.
三、数组名作为函数参数
如果一个实参的数组,想在函数中改变此数组的元素的值,实参和形参的对应关系有4种:
-
实参和形参都是数组名
a是实参数组首地址,那么ba是形参数组首地址,a和ba共用一段内存,也就是说,再调用changevalue期间,a和ba指的是同一个数组。
-
实参用数组名,形参用指针变量
-
实参和形参都用指针变量
-
实参为指针变量,形参为数组名。
四、指向多维数组的指针和指针变量探究
可以把二维数组名a看成一个一维数组,这个一维数组有三个元素:a[0],a[1],a[2],每个元素又是一个包含4个元素的一维数组。
- a:二维数组名,也是整个二维数组的首地址。 假设第0行的首地址是1000。
int a[3][4]; int *p; p=(int *)a;//有时将数组名赋给指针变量,系统不答应,那么就用强制转化符。
- a+1,a+2 分别代表 第一含首地址和第二行首地址。所以a+1跳过16个字节的,也就是a=1000,a+1=1016,a+2=1032.
-
这表示a[0], a[1], a[2]是一维数组名。C语言规定数组名代表数组的首地址,所以有如下:
- 第0行第1列元素地址表示方法有:
&a[0][1] a[0]+1 ----1004p=&a[0][1];
等价于p=a[0]+1;
- 结论:
a[0]等价于*a,都是地址1000, a==*a,都是地址;
a[0]+1等价于*a+1,等价于&a[0][1],等价于1004;
a[1] 等价于*(a+1),等价于1016;
a[1]+2 ,等价于*(a+1)+2,等价于&a[1][2],等价于1024.注意不要把 *(a+1)+2写成*(a+3),那就变成了a[3]; - a[0]+1 等价于 *a+1,等价于&a[0][1] ,等价于 1004,这是个地址。
*(a[0]+1)就代表 a[0][1] 的值;*(*a+1)也是a[0][1]的值
也有:*(a[1]+2), a[1][2]的值,*(*(a+1)+2),都表示第1行第2列元素值。
在二维数组中,a[i]和&a[i]地址值是一样的。
实践:
五、指针数组和数组指针
指针数组:
首先这是个数组,数组中有10个元素,每个元素都是个指针,相当于定义了10个指针变量。
int *p1[10];
数组指针:
int (*p)[10];
这是一个指针变量,这个指针变量用来指向含有10个元素的一维数组。