二维数组和二级指针
1.前言
本文所用到的部分基础知识可以查看此文:
http://blog.youkuaiyun.com/xingerr/article/details/72372563说明:
- 二维数组在内存中按照一维的方式进行存储
- 二维数组中的第一维是一维数组
- 二维数组中的第二维是具体的值
- 二维数组的数组名可以看做是常量指针
array[2][4]
根据选择不同可以为2行4列,也可以为4行2列
2.二维数组
说明:
- 数组名代表数组首元素的地址
- 数组名可以看做指向数组的常量指针
- 可以看作为一维数组(在内存中存储都是线性一维的)
- 数组中的每个元素都是同类型的一维数组
- 数组定义时可以省略第一个的大小(系统自动计算),如:int a[][3];
示例1:
int main()
{
int a[5][5]; //定义二维数组
//int (*p)[4]; //定义数组指针(指向4*4字节大小的数组)(也就是每次p+1地址向后走四个字节大小)
int (*p)[5]; //定义数组指针(指向5*4字节大小的数组)
p = a; //将二维数组的数组名给数组指针p
printf("%d\n", &p[4][2] - &a[4][2]); //打印两个地址相减的结果,应该为0,(如果是4*4字节大小的结果为-4)
return 0;
}
- 示例2:
void print(int a[], int n)
{
int i = 0;
for(i = 0; i < n; ++i)
{
/*用一维方式遍历二维数组并打印*/
printf("%d ", a[i]);
}
putchar(10);
}
int main()
{
int a[3][3] = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
int *p = &a[0][0]; //定义一级指针存放数组首元素的地址
print(p, 9);
/*------------------分割线----------------------*/
int i = 0;
int j = 0;
for(i = 0; i < 3; ++i)
{
for(j = 0; j < 3; ++j)
{
/*正常双重循环打印数组*/
/* 因为一维数组a[i] = *(a+i),同理二维a[i][j] = *(a[i] + j) = *(*(a + i) + j) */
printf("%d ", *(*(a + i) + j));
}
}
putchar(10);
return 0;
}
- 示例3:
int** Malloc(int row, int col)
{
/*给二维数组申请动态空间,row为行数,col为列数*/
int** ret = (int **)malloc(sizeof(int*) * row);
/*定义二级指针ret,并申请row大小的空间,用来存放一级指针*/
int* p = (int *)malloc(sizeof(int) * row * col);
/*定义一级指针p,并申请大小为row*col的空间,存放每行的首地址*/
int i = 0;
if(ret && p)
{
/*对内存申请是否成功进行判断*/
for(i = 0; i < row; ++i)
{
/*对每一行进行分配内存(p指向一维数组的首地址,每次取出相应的列数大小的字节给每一行)*/
ret[i] = (p + col * i);
}
}
else
{
free(ret);
free(p);
return NULL;
}
return ret;
}
void Free(int** a)
{
/*释放内存*/
free(a[0]);
free(a);
}
3.二级指针
说明:
- 因为指针变量会在内存中占用一定空间,所以可以定义指针保存指针变量的地址值
- 二级指针是解决指针的传值调用和传址调用的问题
示例:
int reset(char** p, int size, int new_size)
{
/*如果申请的内存没有使用完,则进行清空释放*/
int ret = 1;
int i = 0;
int len = 0;
char* pt = NULL;
char* temp = NULL;
char* pp = *p; //定义一级指针pp接收二级指针p里面存放的指针的地址
if((p != NULL) && (new_size > 0))
{
pt = (char *)malloc(new_size); //申请一个新的空间(大小为前面申请内存使用过的大小)
temp = pt; //临时变量进行指针操作
len = (size < new_size) ? size : new_size;
/*三目运算符选取size和new_size两者较小的给len*/
for(i = 0; i < len; ++i)
{
/*将以前申请的内存里的值进行复制到新的内存中*/
*temp++ = *pp++;
}
/*释放以前的内存*/
free(*p);
*p = pt; //返回新的内存地址
}
else
{
ret = 0;
}
return ret;
}
int main()
{
char* p = (char*)malloc(5); //动态申请内存大小为5的空间,地址给p
printf("%0x\n", p); //打印申请的内存空间的地址
if(reset(&p, 5, 3))
{
/*将内存缩小为3个字节大小*/
printf("%0x\n", p); //打印新的内存空间的地址
}
return 0;
}
4.参考
- 《C和指针》