多维数组和多维指针
程序员文章站
2024-03-04 15:45:11
...
指针和数组(下)
专题四:指针和数组(下)。包括以下章节:
- 指针数组和数组指针分析
- 多维数组和多维指针
- 数组参数和指针参数分析
- 函数与指针分析
指向指针的指针
- 指针变量在内存中会占用一定的空间
- 可以定义指针来保存指针变量的地址值
-
为什么需要指向指针的指针?
- 指针在本质上也是变量
- 对于指针也同样存在传值调用与传址调用
实例分析2-1:多级指针的分析与使用
2-1.c
#include <stdio.h>
#include <malloc.h>
//char** p:p指向的是一个char*指针
//int size:原本的空间大小
//int new_size:设置新的空间大小
int reset(char**p, int size, int new_size)
{
int ret = 1;
int i = 0;
int len = 0;
char* pt = NULL;
char* tmp = NULL;
char* pp = *p;
//判断传入参数是否合法
if( (p != NULL) && (new_size > 0) )
{
pt = (char*)malloc(new_size);
tmp = pt;
len = (size < new_size) ? size : new_size;
for(i=0; i<len; i++)
{
*tmp++ = *pp++;
}
free(*p);//释放main函数中p指向的空间
*p = pt; //main函数中p重新指向pt申请的空间
}
else
{
ret = 0;
}
return ret;
}
int main()
{
char* p = (char*)malloc(5);
printf("%0X\n", p);
if( reset(&p, 5, 3) )
{
printf("%0X\n", p);
}
if( reset(&p, 3, 12) )
{
printf("%0X\n", p);
}
return 0;
}
结果:
二维数组与二级指针
- 二维数组在内存中以一维的方式排布
- 二维数组中的第一维是一维数组
- 二维数组中的第二维才是具体的值
- 二维数组的数组名可看做常量指针
实例分析2-2: 以一维的方式遍历二维数组
2-2.c
#include <stdio.h>
#include <malloc.h>
void printArray(int a[], int size)
{
int i = 0;
//a是一个指针,64位系统中占8字节(32位系统4字节)
printf("printArray: %d\n", sizeof(a));
for(i=0; i<size; i++)
{
printf("%d\n", a[i]);
}
}
int main()
{
int a[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
int* p = &a[0][0];
//int a[3][3]:a是一个指向指针的指针(int** p)
//第一维是一个指针数组,元素类型为int(*)[3],内容为:[a[0], a[1], a[2]]
//第二维是一个int[6]类型数组,元素类型是int,内容为:[0, 1, 2, 3, 4, 5, 6, 7, 8]
printf("%0X\n", &a); //&a指针类型:int(*)[][3]
printf("%0X\n", a); //a指针类型:int(*)[3];a指向a[0]的地址(指向一维数组的第一个元素的地址)
printf("%0X\n", a[0]); //a[0]指针类型:int(*)[3]
printf("%0X\n", &a[0][0]); //&a[0][0]指针类型:int*
printf("%0X\n", a[1]);
printf("%0X\n", &a[1][0]);
printf("%0X\n", a[2]);
printf("%0X\n", &a[2][0]);
printf("%d\n", a[0][0]);
printf("%d\n", a[1][0]);
printf("%d\n", a[2][0]);
printArray(p, 9);
return 0;
}
结果:
数组名
一维数组名代表数组首元素的地址
int a[5] ==> a的类型为int*二维数组名同样代表数组首元素的地址
int m[2][5] ==> m的类型为int()[5] //&m类型:int()[][5]结论
(1). 二维数组名可以看做是指向数组的常量指针
(2). 二维数组可以看做是一维数组
(3). 二维数组中的每个元素都是同类型的一维数组
2-3.c
#include <stdio.h>
int main()
{
int a[5][5]; //a的类型:int(*)[5]
int(*p)[4]; //p的类型:int(*)[4]
p = a; //相当于:&p[0][0] = &a[0][0]
//a[4][2]==>*((unsigned int)a + 4 * sizeof(int[5]) + 2 * sizeof(int))
//p[4][2]==>*((unsigned int)p + 4 * sizeof(int[4]) + 2 * sizeof(int))
//&a[4][2]:看做一维数组,a[4][2]地址相对a[0][0]的地址偏移了4个int[5]+2==>4*5*4+2*4
//&p[4][2]:看成一维数组,p[4][2]地址相对p[0][0]的地址偏移了4个int[4]+2 ==>4*4*4+2*4
printf("%ld\n", &p[4][2] - &a[4][2]);
}
结果:
实例分析2-3: 以指针的方式遍历二维数组
2-4.c
#include <stdio.h>
int main(int argc, char* argv[], char* env[])
{
int a[3][3] = {{0, 1, 2}, {3, 4, 5}, {6, 7, 8}};
int i = 0;
int j = 0;
for(i=0; i<3; i++)
{
for(j=0; j<3; j++)
{
//已知:a[n]可以使用下标方法表示为*(a+n)
//所以:*(*(a+i) + j) ==> *(a[i]+j) ==> a[i][j]
printf("%d\n", *(*(a+i) + j));
}
}
}
结果:
手把手教你写代码:如何动态申请二维数组(以二维指针模拟)
2-5.c
#include <stdio.h>
#include <malloc.h>
int** malloc2d(int row, int col)
{
//申请第一维的数组空间(int(*)[row]类型的指针数组)
int** ret = (int**)malloc(sizeof(int*) * row);
//申请第二维的数组空间(int[row*col]类型的数组)
int* p = (int*)malloc(sizeof(int) * row * col);
int i = 0;
if(ret && p) {
for (i = 0; i<row; i++) {
//一维数组:[&a[0][0], &a[1][0], &a[2][0]](假如row=3)
ret[i] = (p+i*col);
}
}else {
free(ret);
free(p);
ret = NULL;
}
return ret;
}
void free2d(int** a)
{
free(a[0]);//相当于free(p)
free(a);//相当于free(ret)
}
int main(int argc, char* argv[], char* env[])
{
int** p = malloc2d(3, 3);
p[0][0] = 0;
p[0][1] = 1;
p[1][1] = 2;
p[1][2] = 3;
p[2][0] = 4;
p[2][2] = 5;
int i = 0;
int j = 0;
for(i=0; i<3; i++)
{
for(j=0; j<3; j++)
{
printf("_=%d, *=%d\n", p[i][j], *(*(p+i) + j));
}
}
free2d(p);
return 0;
}
结果:
小结
- C语言中只有一维数组,而且数组大小必须在编译期就作为常数确定
- C语言中的数组元素可是任何类型的数据,即数组的元素可以是另一个数组(的指针)
- C语言中只有数组的大小和数组首元素的地址是编译器直接确定的
上一篇: IO流之字节流
下一篇: Android编程实现提取网址链接的方法