C 二维数组,以及自定义二维数组
我们通常情况下是这样定义一个二维数组的:
int a[10][15];
我们分别查看一下a,a[0],*a
都是一样的值吧
我们可以这么理解: a是一个数组的数组
a是数组首元素的地址,a的首元素是一个15个元素的数组,a[0]和a[0]的首元素(a[0][0]
)的地址是同一个地址
所以有人可能会想int **pa 是不是 跟a同一个类型的
我们可以尝试下面的代码:
int a[4][2]=0x1234;
int **ppa=a;
//尝试写入数据
**ppa=1;
我们发现段错误,说明出错了,而且ppa并不能代表a
我们把a,*a,**a,ppa,* ppa
打印出来
a和ppa的值相同没问题,因为是指向同一个地址,*a
仍然是a的首地址,*ppa
直接解引用了
所以**ppa相当于向0x1234写入数据所以发生了段错误!
如果想理解好这个我们先看一下c语言多维数组的内存是什么样的:
实际上,在内存中,多维数组也是像一维数组一样是连续的,只不过我们把这个数组抽象了一下,
我们让这个数组的首地址赋值给一个int**
指针,那么这个指针会认为是一个int*
数组的地址
(就是一个数组里面保存的都是指针),所以这样解引用会发生错误
解决方法:
使用指向多维数组的指针:
int (*pa)[2]
;//注意和int *pa[2]
区别,后者是一个保存int*
的数组
比如我们在函数传参的时候
这样会导致后面的2是固定的,编程的时候会受到一些限制
int func(int (*pa)[2],int l);
对 int (*p)[2]
的理解:
int a[4][2];
int (*pa)[2]= a;
printf("%p\n",(char*)&pa[1]-(char*)pa);
自增一次多走了sizeof第二个维度的长度
如果是函数定义的话,也可以:
int func(int a[][2],int l)
这样a
第一个维度可以不是固定的,第二维度是固定的,也不是很方便,我们如果定义动态二维数组的话一般不适用多维数组,适用数组的数组
数组的数组(自定义二维数组):
就是用一个int**ppa来指向一个区域,这个区域内每一个元素都是一个指针,每一个指针都指向一个数组
const int col = 5;
const int row = 5;
int **t = (int **)malloc(col*sizeof(int*));
for(int i = 0;i<col;i++)
t[i]=(int*)malloc(row*sizeof(int));
当然,我们也可以把这些不连续的小空间放在一起申请
int **t = (int **)malloc(col*sizeof(int*));
int *p = (int*)malloc(col*row*sizeof(int));
for(int i = 0;i < col;i++)
t[i]=p+col*i;