首先解释几个概念:
1.数组指针,即指向数组的指针。其本身是一个指针变量,变量中保存的值是一个数组的起始地址。
int (*p)[10];
画图画图:
这样一种结构,变量中保存的使数组的开始地址。
所以,我们就可以像下面这样写
int a[10] = {1,2,3,4,5};
// 数组名就表示数组的首地址,所以可以直接赋值
int (*p)[10] = a;
for(int i=0;i<5;i++){
// 取值的时候因为是指针,先取出地址所指向的值,然后因为是数组,所以用[i]
printf("%d ",(*p)[i]);
}
从上面我们可以看出来,数组指针与我们的二维数组的结构是一样,注意,这里说的是结构一样,数组指针这个变量和数组名还是有区别的。
2.指针数组,即一个数组,其中存放的是指针。
// 开了一个指针数组,数组的容量为10
int *p[10];
就是上面这个结构,这个结构与我们的一维数组是一样的,只不过我们的一维数组中一般保存的是值,但是这里面保存的是指针。
从上面的内存结构我们可以看出,数组指针的结构与我们的二维数组是类似的。但是与指针数组的结构是不一样的。
下面是我的一些测试代码:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char box[][10] = {"11111111","22222222","33333333","44444444"};
char *b[8] = {"11111111","22222222","33333333","44444444"};
char (*d)[10] = {"11111111","22222222","33333333","44444444"};
printf("%d\n",sizeof(box));
// 指针数组能用sizeof得到大小,因为这个b变量不一般
// 他代表的是整个数组,所以他用sizeof能测量出整个数组的大小
// sizeof这是由编译器处理的,不是运行时计算的,是编译器编译
// 的时候就会把这个值确定下来。不知道的可以去了解一下
printf("%d\n",sizeof(b));
// 数组指针不能使用sizeof得到正确的大小,因为它本身只是一个普通的指针,所以是4个字节
printf("%d\n",sizeof(d));
for(int i=0;i<4;i++){
// box每次加1,但是地址值加的不是1,而是10,因为二维数组的一维长度是10
// 这是跟指针步长相关的,不同类型的指针+1,指针移动的位置与指针类型有关
printf("%d ",box+i);
printf("%s ",*(box+i));
}
printf("\n");
for(int i=0;i<4;i++){
// b+1,地址加的是4,说明该数组的中保存的类型是int类型的地址
printf("%d ",b+i);
printf("%s ",*(b+i));
}
printf("\n");
for(int i=0;i<4;i++){
// 与二维数组是一样的,+1,指针移动10位,这就是指针类型的原因
// 该指针指向的是一个长度为10的一维数组,所以一定10位
printf("%d ",d+i);
printf("%s ",*(d+i));
}
printf("\n");
fun(box);
printf("\n");
func(b);
return 0;
}
void fun(char (*a)[10]){
for(int i=0;i<4;i++){
// 数组指针的访问方式
printf("%s ",a+i);
}
}
void func(char *a[10]){
for(int i=0;i<4;i++){
// 指针数组的访问方式
printf("%s ",*(a+i));
}
}
其实这其中很多东西都是编译器进行的处理,你一个int类型变量加1,其结果看起来就是加1,但是我一个int类型指针变量加1,其值加了4,这就是编译器在其中做了手脚,编译器中由符号表,他记录你这个变量代表的类型,然后在你加1的时候根据类型进行加1操作,得到不同的加1效果。