指针是可变数组的首地址。正因为是可变数组,所以一般使用指针时都是采用动态内存分配和释放的方式。一维指针形式简单,容易理解。平时应用较多。二维数组和二维指针比较复杂,并且在动态内存分配与释放方面比较复杂且难以理解。但是二维数组和二维指针是非常有用的。
考虑以下应用:对一幅图像进行模板运算。这必然会牵涉到对图像的各象素点的操作。此时使用一维指针进行图像传递时,不可避免的会使用形如*(p+i*width+j)的方式完成对图像象素点的访问。这种方式很不直观并且编写程序时容易出错。如果使用二维指针进行图像数据的传递,则会收到很好的效果。可以采用p[i][j]的方式直接操作象素点,直观又便于维护。因此掌握二维数组和二维指针是必要的。
使用http://www.wangchao.net.cn/bbsdetail_59038.html中的示例。
定义如下3个二维数组和二维指针进行说明:
1. int** ptr;
2. int *ptr[M];
3. int (*ptr)[M];
以上都是存放整数的二维数组,并且都可以通过ptr[i][j]的形式访问内容。但是它们之间有很大的差别。以下依照文中提到的方面进行分析。
l 内容
三个ptr本身都是指针,并且是二维指针,但是它们的最终内容总是整数。但中间内容,形如ptr[i]并不是整数,而是指针int *.
l 意义
1. int** ptr 表示指向(一组指向整数数据指针)的指针;
2. int *ptr[M] 是指针数组,表示指向(M个指向整数指针)的指针;
3. int (*ptr)[M]表示指向一组(指向包含M个整型数据的指针)的指针。
l 所占空间
1和3占用一个内存空间,在32位平台上为4个字节,也就是一个指针。
2是M个指针,在其定义过程中编译器即对其进行了分配,占用4*M共4M个字节。
l 用法
1. int** ptr 表示指向(一组指向整数数据指针)的指针,是一个二维指针。在其定义过程中,编译器并不对其进行内存的分配,因此必须自己管理其内存的分配与释放。典型使用如下:
int** ptr;
int i,j;
ptr = (int**)malloc((sizeof(int*))*M);
printf("The Address of ptr:%10x\n",ptr);
for (i=0;i<M;i++)
{
ptr[i] = (int*)malloc(sizeof(int)*N);
printf("The Address of ptr[%d]:%10x\n",i,ptr[i]);
}
//采用如上内存分配方法,意味着将ptr初始化为M*N的二维数组首地址
//可以访问ptr[0:M-1][0:N-1]的数据
//操作
for (i=0;i<M;i++)
{
free(ptr[i]);
}
free(ptr);
使用上述方法分配内存,最终ptr耗费的内存空间为M*sizeof(int*)+M*N*sizeof(int)
2. int *ptr[M] 是指针数组,表示指向(M个指向整数指针)的指针。是一个二维指针。但是在定义的时候,编译器已经为ptr指向的M个指向整数的指针ptr[0:M-1]分配了内存。也就是说,定义之后即可得到ptr的地址以及用于存放ptr[0:M-1]的内存空间4MB。要使用ptr必须对ptr[i]分配内存。分配内存后,ptr地址相应内存空间填入ptr[i]指向内存地址。使用如下操作:
int* ptr[M];
int i,j;
printf("The Address of ptr:%10x\n",ptr);
for (i=0;i<M;i++)
{
ptr[i] = (int*)malloc(sizeof(int)*M);
printf("The Address of ptr[%d]:%10x\n",i,ptr[i]);
}
//采用如上内存分配方法,意味着将ptr初始化为M*N的二维数组首地址
//可以访问ptr[0:M-1][0:N-1]的数据
//操作
for (i=0;i<M;i++)
{
free(ptr[i]);
}
//free(ptr); //此处不释放ptr内存,是因为ptr的内存是由编译器分配的。
使用上述方法分配内存,最终ptr耗费的内存空间为M*sizeof(int*)+M*N*sizeof(int),其中M*sizeof(int*)为编译器分配,M*N*sizeof(int)为程序员自己分配。
3. int (*ptr)[M]表示指向一组(指向包含M个整型数据的指针)的指针。该定义限定了ptr[i][0:M-1],所有指针ptr[i]必须指向长度为M的数组。使用方式如下:
int (*ptr)[M];
int i,j;
printf("The Address of ptr:%10x\n",ptr);
ptr = (int (*)[M])malloc(sizeof(int)*M*N); //一次分配连续内存
printf("The Address of ptr:%10x\n",ptr);
for (i=0;i<N;i++)
{
// ptr[i] = (int [M])malloc(sizeof(int)*M);
printf("The Address of ptr[%d]:%10x\n",i,ptr[i]);
}
//采用如上内存分配方法,意味着将ptr初始化为N*M的二维数组首地址
//可以访问ptr[0:N-1][0:M-1]的数据
//操作
free(ptr);
使用上述方法分配内存后,ptr所占内存空间为M*N*sizeof(int)(不考虑不同操作系统用于管理的内存)。ptr内存空间中保存的为最终内容而非ptr[i]地址。