目录
前言
关于C语言中的数组指针与指针数组的概念,是C语言中难度略大的内容。本文使用大白话,结合图片和实验,力图把这两个概念介绍一下
一、指针数组
指针数组比较简单。首先记住 “指针数组其实是一个数组”;
1.指针数组概念
int a[5]; //定义一个普通数组,数组的每个元素是int类型
int * a[5]; //定义一个指针数组,数组的每个元素是int* 类型
Point * a[5]; //定义一个指针数组,数组的每个元素是 Point * 类型
int****** a[5]; //定义一个指针数组,数组的每个元素是int****** 类型
地址数内存单元的编号,在32位操作系统中地址总线宽度为32,因此采用一个四字节的数来表示一个地址,在上面代码定义的三个指针数组中,数组的元素用来容纳一个地址,因此每个元素所占4字节。
2.指针数组赋值
1.普通指针变量的赋值
int i;
int * p = &i; //变量p存放的是变量i的地址
char * a = "come on!"; //变量 a 存放的是字符串的地址(字符‘c’所占内存单元的地址)
2.指针数组的赋值
char a,b;
char * p[2];
p[0] = &a;
p[1] = &b;
//定义了两个char 型变量a,b以及一个长度为2的指针数组,指针数组的每个元素用来容纳一个char 型数据的地址,最后将两个char 类型变量的地址赋值给数组的不同元素
char * a[2]={"come on!","hhh"};
//指针数组的元素容纳字符串的地址;
二、数组指针
1.数组指针概念
数组指针的实际运用比较少,但是在一些公司的面试笔试中经常出现,原因在于可以通过对数组指针的考察,测试一个求职人员对指针概念的掌握程度。数组指针几乎是C语言里面最难理解的类型。
好了,一言以蔽之,“数组指针其实是一个指针”,既然是指针,那么它的长度还是4个字节。
int (*p)[5];//定义一个指向一维数组的指针变量p,类型为int(*)[5];
char (*p)[5]; //定义一个指向一维数组的指针变量p,类型为 char(*)[5];
int (*p)[2][2];//定义一个指向二维数组的指针变量p,类型为int(*)[2][2];
char(*p)[3][3][3];//定义一个指向三维数组的指针变量p,类型为char(*)[3][3][3];
可能之前看惯了类似于 char *,int *,等指针变量的类型名,对于类似于char *[5],这种类型不太适应。
ps: 思考一下 int *p[5] 和 int (*p)[5]区别?
答:前者是指针数组,后者是数组指针,前者的每个元素可以容纳 int * 型地址,对于后者,p是 int(*)[5]型指针。
2.数组指针的运算
看一段代码;
代码如下
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int arr[5]={1,2,3,4,5};
int * p;
printf("%d\n",sizeof(arr));
p = arr;
printf("p: %p\n",p);
printf("aar : %p\n\n",arr);
printf("&arr[0] :%p \n\n", &arr[0]);
printf("&arr : %p\n\n",&arr);
printf("arr+1 : %p\n\n", arr+1 );
printf("&arr[4]: %p\n\n ", &arr[4]);
printf("&arr[4]+1: %p \n\n",&arr[4]+1);
printf("&arr+1 : %p\n", &arr+1);
return 0;
}
运行结果:
20
p: 000000000062FE00
aar : 000000000062FE00
&arr[0] :000000000062FE00
&arr : 000000000062FE00
arr+1 : 000000000062FE04
&arr[4]: 000000000062FE10
&arr[4]+1: 000000000062FE14
&arr+1 : 000000000062FE14
--------------------------------
Process exited after 0.01611 seconds with return value 0
请按任意键继续. . .
1.数组变量名与地址
采用 sizeof 关键字对数组变量arr计算求得结果是 20;由此可见arr不是地址,但是将arr赋值给一个int * 型指针变量,输出的又为数组第一个元素的首地址,在这里,笔者以为,不可以说数组变量名就是地址,只能说有时候数组变量名可以表示数组首元素的首地址。参考《C语言深度剖析》那本书,指针变量变量名的其实指的是内存中的那一块区域。
2.&arr[0]与&arr
二者输出相同,但含义不一样,&a[0]指的是数组首元素的首地址,类型为int * 类型。&a指的是数组变量的地址,类型为 int (*) [5]。
3.&arr[0]++与&arr++
&arr[0]++ 指的是arr[1]元素的首地址;
&arr++ 指的是数组末元素末地址后面那个字节的地址,对&arr 加1,相当于加了 sizeof(arr);
4.利用数组指针访问数组元素
代码:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int arr[9]={1,2,3,4,5,6,7,8,9};
/* int arr1[2][2]={1,2,3,4};
int * p;
printf("%d\n",sizeof(arr));
p = arr;
printf("p: %p\n",p);
printf("aar : %p\n\n",arr);
printf("&arr[0] :%p \n\n", &arr[0]);
printf("&arr : %p\n\n",&arr);
printf("arr+1 : %p\n\n", arr+1 );
printf("&arr[4]: %p\n\n ", &arr[4]);
printf("&arr[4]+1: %p \n\n",&arr[4]+1);
printf("&arr+1 : %p\n", &arr+1);
*/
int (*P_arry)[9] = &arr;
printf("(*P_arry)[1]= %d\n",(*P_arry)[1]); //arr[1]
printf("(P_arry[0][1]= %d\n",P_arry[0][1]); //P_arry[0][1] = *(P_arry+0)[1]=*(P_arry)=arr[1]
printf("*(*P_arry+1)= %d\n",*(*P_arry+1)); //*arr=arr[1]
int (*px)[2][2] = (int (*)[2][2])(&arr[0]);
printf("%d\n",(*px)[1][1]);
px ++; //px++ <==> px+sizeof(int)*4
printf("%d\n",(*px)[0][0]); //此时 指针变量 px的值与 &a[7]相等
return 0;
}
运行结果:
(*P_arry)[1]= 2
(P_arry[0][1]= 2
*(*P_arry+1)= 2
4
5
--------------------------------
Process exited after 0.02505 seconds with return value 0
请按任意键继续. . .
总结
,代码注释都比较清楚,先不总结了啊,回头在写!!