数组指针 和 指针数组

数组指针 和 指针数组,第1张

        在C语言中,指针是个神奇的东西,在window底层对指针的妙用无处不在。


这里来总结数组针指的小结。


在内存里面系统就是通过指针来寻找数组的每个元素的。




一、数组指针 1.一维数组:

数组指针:指向一个数组的指针。


int arr[]={1,2,3,4,5,6,7,8,9};

        这里有个整形数组 arr,这里我们知道arr是数组名,也是地址首元素的地址。


那么能不能定义一个指针来指向这个数组并调用数组里面的元素呢。


        其实是可以的。


那么指针的类型是什么样的呢。


我们定义指针的时候:

int a=10;
int* p=&a;
printf("%d",*p);

         这里p就是一个指向a地址的指针,取地址a (&a),取得的就是a的地址,解引用(*p)就是获得变量a上存的值。


        这里可以总结一个小规律,一个变量取地址(&)就相当于原来的类型加上一个*,一个指针解(*)引用就相当原来的类型减一个*。


        &a(取地址)的后获得的类型就是 int*,*p(解引用)后获得的类型是 int

那么对于数组来说也是一样的,把数组取地址(&arr),得到的类型是原类型加上一个*。


int (*arr)[];
//注意不是 int *arr[];

那么用来接受这个数组地址的类型也该是

int arr[10];
int (*p)[10]=&arr;

        这里指针p是一个指针,指向一个数组,数组的返回类型是int类,所以p就叫数组指针,表达了整个数组。


 PS:

int (*p1)[10];
int (*p2)[5];

         这里 [ ] 里面10跟5的差别很大,是10的时候 p+1,跳过数组的10个元素,是5的时候则跳过5个元素。


void print(int (*p)[10],int sz) //这种写法属于绕远路,一般写的少
{
	for(int i=0;i

         指针p解引用(*p),原类型去掉一个*,就是 int p[10],这里p就代表数组名,数组名就是首元素的地址。


所以解引用数组指针,就是数组首元素地址。


        那么 首元素地址再加上一个数 i,就能取到第i个元素的地址 *(*p+i )

        

PS:这里 p,&arr,arr的值是一样的,代表的含义不同。


 

数组名:

1.sizeof(arr) ,这里arr表示的是整个数组。


2.&arr,这里也是表示取的整个数组的地址。


然后其他的数组名,都是表示数组首元素地址。


* :虽然地址首元素的地址跟整个数组的地址是一样的,但是 首元素的地址+1,则跳到下一个元素,整个数组的地址+1,则跳过整个数组。


2.二维数组:

        对于二维数组来说,数组指针有又有些不同。


   

void print(int (*p)[3],int c,int r) 
{
	for(int i=0;i{1,2,3},{4,5,6},{7,8,9}};
print(arr,3,3);
//int (*p)[3][3],必须三行三列,才能接收二维数组arr

         在二维数组中 arr 代表的是第一行的地址,相当于*(arr+0)、arr[0]。


也叫行指针。


        会发现这里  int arr[3][3],跟上面的 int (*p)[3]  很相似。


所以这里的 arr也可以理解为一个数组指针指向数组的第一行。


        &arr[0][0],*(arr+0)+0,才是第一个元素的地址(地址是一样的,意义不同)。


             

         按照上面,arr取地址(&arr),原类型加一个*,int (*arr)[3][3],还是要注意不是int* arr[3][3],那么用来接收指向二维数组的指针的类型就是,int(*p)[3][3]。


        解引用p (*p) ,原类型减去一个*,就是 int p[3][3],这里的p代表的是数组第一行的地址,       *(p+i),就获得的是数组第i行首元素的地址,再解引用*(*p),原类型再减去一个*就是int p[3],这里的p就是首元素地址了,*(*(p+i)+j)获得的就是第几行第几个元素。


        这里有多中写法:1.p[ i ][ j ]        2.*( p + i ) [ j ]

         PS:这里的p[3][3],元素的个数必须跟二维数组一样。


 

         PS:理解去*,加*的时候,*是从变量名最近的*号开始的,也就是从最里面的*开始算。



二、指针数组

        那么为什么数组指针不能写成  int*arr[10],这种形式呢。


        因为这种数组代表的意义不同,此数组叫指针数组,意思是一个数组arr,有10个元素,每个元素的类型是 int* 的指针。


int a1,a2,a3;
int *p1=&a1;
int *p2=&a2;
int *p3=&a3;
int *arr[3]={p1,p2,p3};

指针数组也可以定义一个指向数组的指针:

        int* (*arr)[3];        二维数组: int* (*arr)[3][3];

        当然不管是在这里还是在上面,都还可以进行无限的套娃(加*),不过意义已经不大而且几乎使用不到,并且非常复杂。


 

对于指针数组来说,则就可以使用 int * *arr(二级指针)来接受数组。


void test(int* *p){ }

int *arr[3];
test(arr)  //不是&arr

但是为什么某些编译器或者网站则使用 int* * arr来接受二维数组呢?

其实它们不是标准的二维数组,只是二维数组的一个模拟


总结

        光是在数组里面的指针的意义和用法都多种多样,要熟练指针,多练习和运用。


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/562282.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-01
下一篇 2022-04-01

发表评论

登录后才能评论

评论列表(0条)