一、指针与数组的基本用法
- 数组指针是指数组在内存中的起始地址,数组元素的地址是指数组元素在内存中的起始地址
- 一维数组的数组名为一维数组的指针(起始地址)
例如:
double x[8];
因此,x为x数组的起始地址
- 设指针变量px的地址值等于数组的指针x(即指针变量px指向数组的首元数),则:
x[i] 、*(px+i)、*(x+i) 和px[i]具有完全相同的功能:访问数组第i+1个数组元素。
- 使用指针遍历一维数组
- 指针变量和数组在访问数组中元素时,一定条件下其使用方法具有相同的形式,因为指针变量和数组名都是地址量
1.数组指针与指针数组:
数组指针:是一个指向数组的指针
指针数组:是一个储存指针的数组
数组指针(表示一维数组)
#include <stdio.h>int main()
{int (*p)[3];/*定义了一个数组指针,指向了一个数组长度为3的一维数组,注意是指向一个数组,所以赋值给他的地址要是数组类型的地址可以这样理解:一维数组名就是一个指针这里只是用指针的形式代替了数组名 ,注意这里的3要和指向的数组长度相同*/ int a[3] = {1,2,3};p = &a;/*将数组a地址赋值给p,此时(*p)[i]相当于a[i],注意不能写成p=a,或者p=&a[0]因为指针p是指向一个数组,p=a表示p指向首个元素的地址,虽然&a,&a[0],a的结果是一样的(这是因为数组一般用其首元素地址表示) */printf("数组指针指向一维数组的遍历:\n"); for(int i=0; i<3; i++){printf("%d\n",(*p)[i]);}/*这里要用指针遍历输出a不能用*(p+i)方式输出,因为p表示数组a的地址(一般用数组中首个元素地址表示), p++表示p要增加3*4个字节长度(3为数组指针指定的长度,4为int所占空间大小) */ printf("--------------------------\n");printf("&a=%d\n",&a);//输出a的地址 printf("p=%d\n",p);//p指向了数组a,所以输出为a的地址(一般用数组中首个元素地址表示)printf("*p=%d\n",*p);//既然p指向了数组a,那么*p则为数组a本身(一般用数组中首个元素地址表示)printf("p+1=%d\n",p+1);printf("*(p+1)=%d\n",*(p+1));//,运用公式*(p+1) == p[1],可以想象成刚好超过a长度的那个地址,p+1表示p要增加3*4个字节长度(3为数组指针指定的长度,4为int所占空间大小)==*(p+1)printf("**p=%d\n",**p);//p指向a,*p表示a本身(一般用数组中首个元素地址表示),那么**p表示*a,表示数组首元素。printf("p[0]=%d\n",p[0]);//p[0] == *p ,*p又是a本身,所以输出a首元素地址printf("*p[0]=%d\n",*p[0]);//既然p[0]为数组首元素地址,那加上个*就为a的首元素 return 0;
}
二、指针与数组使用注意事项
1、数组名和指针有什么区别
1)含义不同
数组名代表一个数组,存放相同类型的元素指针代表存储地址的变量
2)使用不同
数组名代表一个数组,存放相同类型的元素指针代表存储地址的变量
3)长度不同
sizeof数组名,代表数组占用的总空间
sizeof指针,和操作系统有关,32位系统,4个字节
4) 本质不同
指针变量是地址变量,而数组名是地址常量
三、总结
int a[3][4]={0};
1、printf(“%d\n”,sizeof(a));
解:sizeof(a)表示计算整个数组的大小,为344=48
2、printf(“%d\n”,sizeof(a[0][0]));
解:a[0][0]表示数组a中的第一个元素,sizeof(a[0][0])计算数组a中第二个元素所占空间大小;
3、printf(“%d\n”,sizeof(a[0]));
解:a[0],相当于第一行的地址,表示第一行所有元素。为:4*4=16;
4、printf(“%d\n”,sizeof(a[0]+1));
解:a[0]没有单独放在sizeof()内部,也没有取地址,所以它现在表示第一行第一个元素的地址,a[0]+1表示第一行第二个元素的地址;sizeof()计算地址为:4/8;
5、printf(“%d\n”,sizeof(*(a[0]+1)));
解:对第一行第二个元素解引用,表示计算第二个元素所占空间的大小,为4;
6、printf(“%d\n”,sizeof(a+1));
解:a是二维数组的数组名,并没有取地址,也没有单独放在sizeof()内部,所以a表示二维数组首元素地址,即第一行的地址,a+1就表示第二行的地址;计算地址为:4/8;
7、printf(“%d\n”,sizeof(*(a+1)));
解:对第二行解引用,计算第二行所有元素大小,为16;
8、printf(“%d\n”,sizeof(&a[0]+1));
解:&a[0]+1表示取出第二行的地址,计算地址大小为4/8;
9、printf(“%d\n”,sizeof((&a[0]+1));
解:16,(&a[0]+1)表示对第二行解引用,求第二行所有元素所占空间的大小;
10、printf(“%d\n”,sizeof(*a));
解:16;a没有单独放在sizeof()内部,所以a表示二维数组首地址即:第一行的地址,*a对第一行解引用,求第一行所有元素所占空间的大小;
11、printf(“%d\n”,sizeof(a[3]));
解:16;a[3]其实是第四行的地址(如果存在的话),其实在内存中并不存在a[3],但是sizeof并不会计算表达式的值,它也会通过表达的类型计算它所占空间大小;我们知道,一个表达式:int a= 3+5;a有两个属性,一个值属性:8,一个类型属性:int,而size of()是计算变量所占空间大小,即表达式的类型所占空间大小,它并不会计算表达式的值。