前言
在C语言的学习中,二维数组的学习中遇到了下面的问题:
如何动态分配二维数组?
一、关于一维数组的动态内存分配
对于一维数组来说,比如定义一个整型数组,数组的首地址可以用一级指针存放,那么我们可以定义一个指针,对指针进行动态内存分配,比如接下来我想申请一个元素个数为n的一维数组,n由用户输入,代码如下:
#include <stdio.h>
#include <stdlib.h>
int main(int argc,const char *argv[])
{
int *p=NULL;
int n=0;//n为想申请的内存空间
scanf("%d",&n);
p=(int*)malloc(n*sizeof(int));
//可对数组进行一系列操作
free(p);
return 0;
}
这里之所以这样操作,是因为一维数组的首地址可以存放在一级指针中,一级指针p也可以用p[0]这样的格式来使用数组中的元素。
但是这样操作是不行的。
#include <stdio.h>
int main(int argc,const char *argv[])
{
int n=0;
scanf("%d",&n);
int a[n];
return 0;
}
报错,这样定义并没有把a赋过去,这样就会让我们认为定义数组时[]内只能存放常量,实际上我也是这样记的,实际上在一维数组中这样记是没有错误的。
二、关于二维数组的动态内存分配
根据一维数组的动态内存分配过程,我推得首先要把二维数组的首地址放在一个类型的指针中,再对这个指针进行动态内存分配相应的内存空间,即可完成需求。
首先我们知道对于二维数组来说,二维数组实质上是多个一维数组,类比一维数组,当我们需要存放一维数组的首地址时,一维数组的实质是多个相同类型的元素,所以只需要定义一个相同类型对应的指针来存放一维数组名即可存放。
但是对于二维数组,同样的,需要定义一个相同数组类型的指针来存放二维数组名,因此引入了数组指针。
示例:
int a[3][4];
int (*p)[4]=a;
这里出现了[],我们在一维数组中知道类似a[n]这样先写入n再定义是不行的。所以如果提出需求要动态内存分配一个m*n的二维数组,m和n都需要用户手动输入,此时就发愁了,因为既然定义指针类型时中括号内的值不可以通过手动输入的方法存放变量,那该如何定义指针来进行内存分配呢?
其实接下来使用的方法令我自己都大跌眼镜,因为我实在想不出来定义方法,所以就尝试这样写了一下。
#include <stdio.h>
#include <stdlib.h>
int main(int argc,const char *argv[])
{
int m,n;
scanf("%d%d",&m,&n);
int (*p)[n]=NULL;
p=(int(*)[n])malloc(m*sizeof(int[n]));
int count=1,i,j;
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
p[i][j]=count++;
}
}
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
printf("%d ",p[i][j]);
}
printf("\n");
}
free(p);
return 0;
}
我在定义时直接将n写入了数组指针中,但编译通过,正常输出了结果。
可见m=3,n=4被系统正常接收到了。但明明定义时我写了变量,却被正常定义了。
于是我尝试类似之前这样定义二维数组:
#include <stdio.h>
int main(int argc, const char *argv[])
{
int n=0;
int m=0;
scanf("%d%d",&m,&n);
int a[m][n];
int i=0;
int j=0;
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
a[i][j]=1;
printf("%d ",a[i][j]);
}
printf("\n");
}
return 0;
}
按照一维数组的学习,这样本来应该是编译错误的,但:
编译通过,正常输出。这里二维数组定义时就允许放变量,变量以scanf的方式写入数据。
至于这样的现象是为什么目前我还没有搜到解释,暂时先记住这样的特性,看到这篇文章的朋友也可以解释一下帮助我理解一下。