首先区别一下double **a 与 double *a[]:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
int main(){
int row=20, colum=10;
double **a;
cout<<sizeof(a)<<endl; // 输出为4
double *b[row];
cout<<sizeof(b)<<endl; // 输出为80
}
分析:两段程序都是输出名称a,为什么结果不一样?其实可以类比char * a和char a[10];
当定义成double ** a时,系统并未给其分配内存,a就是一个指针的大小4,当定义为double * b[row]时,系统就会给b分配row个指针,所以b的大小为row*4=80,而每个指针例如b[0]指向double *类型
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
int main(){
char *a;
cout<<sizeof(a)<<endl; // 输出4
char b[10];
cout<<sizeof(b)<<endl; // 输出10
}
接下来看两种定义方法下如何用malloc对其动态分配内存:
double **a 方式:
1)方法1:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
int main(){
int row=20, colum=10;
double **a;
/*
为a分配row个指针,每个指针,如a[0]指向第一行首位置,但此时还未对每一行分配内存
此时各个指针(指向每行的首位置)的地址并不连续
*/
a = (double **) malloc(row * sizeof(double ));
/*
为每一行分配内存,注意a[i]是指向第i+1行的“首指针”
*/
for(int i=0; i<row i++){
a[i] = (double *) malloc(colum * sizeof(double ));
}
/*
注意手动释放空间
*/
for(int i=0; i<row; i++){
free(a[i]);
}
free(a);
// 此内存分配方法的结果是,a[i]所指向的第i行的各个地址是连续的,但是a[0],a[1],a[2],...是不连续的
}
2)方法2:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
int main(){
int row=20, colum=10;
double **a;
/*
这里我们先申请需要的总空间row * colum * sizeof(double),并且让a的第一个指针a[0]指向这块空间,
相当于,我们先把二维数据全放在第1行;那么这些数据必然连续
*/
a[0] = (double *) malloc(row * colum * sizeof(double));
/*
我们本意想让a[1]指向第二行首位置,a[2]指向第三行首位置...那么第二行首位置在哪呢?答案是:a[0]+colum
因此我们手动设置各行首位置a[i];
这样,最终我们的二维数组地址就连续了
*/
for(int i=1; i<row; i++){
a[i] = a[i-1] + colum;
}
/*
注意手动释放空间
*/
for(int i=0; i<row; i++){
free(a[i]);
}
free(a);
}
double *a[row] 方式:
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
using namespace std;
int main(){
int row=20, colum=10;
/*
当定义为下面形式时,相当于已经为每一行分配了一个首地址,a[i]为第i+1行的首地址;
注意,这些地址不连续
*/
double *a[row];
/*
为每一行动态分配内存
*/
for(int i=0; i<20; i++){
a[i] = (double *) malloc(colum * sizeof(double ));
}
/*
手动释放内存
*/
for(int i=0; i<row; i++){
free(a[i]);
}
free(a);
// 上面的方法,最终的二维数组地址同方法一,行内连续,行间不连续
}