一、引言
移动通信中信号的强度:终端在每个地点收到的是多个基站信号的叠加,需要依据强度,判断选择接入哪个基站。
信号强度计算公式:
信号强度计算的是一定时间范围内的平均强度。
相关性检测公式:
二、系统设计要求
计算12个候选小区的强度,其中包括了信号质量较好的小区21和小区27,并进行从强到弱的排序。通过利用确定性信号进行相关性检测,进而抉择是否接入。
三、设计思路及方案
1.整体概况
2.动态内存分配及变量名设计:
double* p=(double*)calloc(CellNum,sizeof(double)); //小区的信号强度
double* sort=(double*)calloc(CellNum,sizeof(double)); //用于小区信号强度排序
double* relevant=(double*)calloc(CellNum,sizeof(double)); //存储每个小区的最大相关
int* Pss_Max=(int*)calloc(CellNum,sizeof(int)); //存储与每个小区最大相关的下标
int* top=(int*)calloc(CellNum,sizeof(int)); //用于信号排序
double* I=(double*)calloc(NumData,sizeof(double)); //存储小区I路信号
double* Q=(double*)calloc(NumData,sizeof(double)); //存储小区Q路信号
double* z=(double*)calloc(NumData-NumPdata,sizeof(double)); //存储小区与PSS的滑动相关
double **Pss_I=AllocateandInit(PssNum,NumPdata); //存储PSS的I路信号
double **Pss_Q=AllocateandInit(PssNum,NumPdata); //存储PSS的Q路信号
double **z_I=AllocateandInit(CellNum,PssNum); //存储每次滑动相关的I路信号
double **z_Q=AllocateandInit(CellNum,PssNum); //存储每次滑动相关的Q路信号
double **max=AllocateandInit(CellNum,PssNum); //存储每个小区与每个PSS相关后的最大相关
double **sum2aveR=AllocateandInit(CellNum,PssNum); //存储每个小区与每个PSS相关后的平均相关
3.功能子函数设计:
//自动计算txt文件数据长度,以最大长度开辟空间,本实验假设每个数据长度相差不大
int AutoCntLen(int Num,int flag)
//二维数组内存动态分配
double ** AllocateandInit(int rows,int cols)
//二维数组内存释放
void FreeMemory(double ** array, int rows)
//读取自同步信号
void ReadPssData(double **Pss_I,double **Pss_Q,int PssNum,int NumPdata)
//读取小区信号
void ReadData(double *I,double *Q,int CellNum,int PssNum,int NumData,int NumPdata,double *p,double **z_I,double **z_Q,double** Pss_I,double** Pss_Q,double *z,double **max,double **sum2aveR,double *relevant,int *Pss_Max)
//信号强度排序
void Sort(double *Sa,double *Sb,int CellNum)
//打印信号强度排序
void PrintSort(double *PSa,double *PSb,int *PSc,int CellNum)
4.C源码
/**************************************************************************
* @brief : 移动通信-信号强度计算
* @author : xdy
* @copyright : 归作者所有
* @version : Version 1.0
* @note : None
* @history : None
***************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define M 100
#define EPS 1e-7
int i,j,k,g,h,t,s,x;
int a,b; //存储小区信号所需的下标
int NumData,NumPdata; //小区每路信号数目,PSS每路信号数目
int CellNum,PssNum; //小区数目,PSS数目
char filename[M]; //创建文件名存储数组
double sum; //信号强度求和
double powand; //平方和
double temp; //用于冒泡排序
FILE *fp; //创建文件指针
/**************************************************************************
* @brief : 自动计算txt文件数据长度,以最大长度开辟空间,本实验假设每个数据长度相差不大
* @param[in] : Num所需打开文件个数;flag标志为0打开PSS文件,反之打开data文件
* @param[out] : None
* @return : 返回所需开辟空间大小
* @others : 本实验假设每个数据长度相差不大
***************************************************************************/
int AutoCntLen(int Num,int flag)
{
int *len=(int*)calloc(Num,sizeof(int));
int c;
int cnt;
for(cnt=0;cnt<Num;cnt++)
{
g=cnt+20;
if (flag==0)
{
sprintf(filename,"C:\\Users\\86185\\Desktop\\通软实验\\180308204701120_第一次实验数据\\第一次实验数据\\PSS%d.txt",cnt);
}
else
{
sprintf(filename,"C:\\Users\\86185\\Desktop\\通软实验\\180308204701120_第一次实验数据\\第一次实验数据\\data%d.txt",g);
}
if((fp=fopen(filename,"rt"))==NULL)
{
printf("Fail to open file!");
exit(0);
}
while((c = fgetc(fp)) != EOF) //C 库函数 int fgetc(FILE *stream) 从指定的流 stream 获取下一个字符(一个无符号字符),并把位置标识符往前移动。
{
if(c == '\n') //碰到换行符,则行数+1
len[cnt]++;
}
len[cnt]=len[cnt]/2;
if(len[cnt]>=len[0])
{
len[0]=len[cnt]; //确认最大数据长度
}
fclose(fp);
}
return len[0];
}
/**************************************************************************
* @brief : 二维数组内存动态分配
* @param[in] : rows二维数组行数;cols二维数组列数
* @param[out] : None
* @return : 二维数组地址
* @others : None
***************************************************************************/
double ** AllocateandInit(int rows,int cols)
{
double** array = (double**)calloc(rows,sizeof(double*)); //分配行指针数组的内存
if (array == NULL)
{
printf("Memory allocation failed.\n");
exit(1);
}
*array = calloc(rows * cols, sizeof(double)); //直接开辟一块连续空间
for (i = 1; i < rows; i++)
{
array[i] = array[0] + i * 2;
if (array[i] == NULL)
{
printf("Memory allocation failed.\n");
exit(1);
}
}
// for (i = 0; i < rows; i++) //分配列的内存并初始化为零,可能造成内存分配不连续
// {
// array[i] = (double*)calloc(cols,sizeof(double));
// if (array[i] == NULL)
// {
// printf("Memory allocation failed.\n");
// exit(1);
// }
//
// }
return array;
}
/**************************************************************************
* @brief : 二维数组内存释放
* @param[in] : array指针数组首地址;rows二维数组行数
* @param[out] : None
* @return : None
* @others : None
***************************************************************************/
void FreeMemory(double ** array, int rows)
{
for (i = 0; i < rows; i++)
{
free(array[i]); // 释放每行内存
}
free(array); // 释放行指针数组内存
array=NULL;
}
/**************************************************************************
* @brief : 读取自同步信号
* @param[in] : Pss_I为PSS的I路信号存储首地址;Pss_Q为PSS的Q路信号存储首地址;
PssNum为PSS文件数目;NumPdata为PSS数据长度
* @param[out] : None
* @return : None
* @others : None
***************************************************************************/
void ReadPssData(double **Pss_I,double **Pss_Q,int PssNum,int NumPdata)
{
printf("读取PSS数据\n");
for(s=0;s<PssNum;s++)
{
printf("正在读取pss%d的数据\n",s);
sprintf(filename,"C:\\Users\\86185\\Desktop\\通软实验\\180308204701120_第一次实验数据\\第一次实验数据\\PSS%d.txt",s);
if((fp=fopen(filename,"rt"))==NULL)
{
printf("Fail to open file!");
exit(0);
}
for(t=0,j=0,h=0;t<2*NumPdata;t++)
{
if(t%2==0)
{
fscanf(fp,"%lf",&Pss_I[s][j]);
j++;
}
else
{
fscanf(fp,"%lf",&Pss_Q[s][h]);
h++;
}
}
fclose(fp); //关闭文件
}
printf("PSS数据读取完成\n");
}
/**************************************************************************
* @brief : 读取小区信号
* @param[in] : I为小区的I路信号存储首地址;Q为小区的Q路信号存储首地址;
CellNum为小区文件数目;PssNum为PSS文件数目;
NumPdata为PSS数据长度;NumData为小区信号强度;
p为小区信号强度;z_I存储每次滑动相关的I路信号;
z_Q存储每次滑动相关的Q路信号;
Pss_I存储PSS的I路信号;Pss_Q存储PSS的Q路信号;
z存储小区与PSS的滑动相关;max存储每个小区与每个PSS相关后的最大相关 ;
sum2aveR存储每个小区与每个PSS相关后的平均相关;
relevant存储每个小区的最大相关 ;
Pss_Max存储与每个小区最大相关的下标;
* @param[out] : None
* @return : None
* @others : None
***************************************************************************/
void ReadData(double *I,double *Q,int CellNum,int PssNum,int NumData,int NumPdata,double *p,double **z_I,double **z_Q,double** Pss_I,double** Pss_Q,double *z,double **max,double **sum2aveR,double *relevant,int *Pss_Max)
{
double *data=(double *)calloc(2*NumData,sizeof(double));
for(i=0;i<CellNum;i++)
{
g=i+20;
sprintf(filename,"C:\\Users\\86185\\Desktop\\通软实验\\180308204701120_第一次实验数据\\第一次实验数据\\data%d.txt",g);
if ( (fp = fopen(filename, "rt")) == NULL )
{
puts("Fail to open file!"); //判断文件是否打开失败
exit(0);
}
sum=0;
printf("\n");
printf("正在读取data%d小区...\n",g);
for(t=0;t<2*NumData;t++) //读取小区数据
{
fscanf(fp,"%lf",&data[t]);
}
printf("计算data%d小区信号强度...\n",g);
for(j=0,h=1,a=0,b=0;j<=2*NumData-1;j+=2,h+=2,a++,b++) //计算信号总强度
{
I[a]=data[j];
Q[b]=data[h];
powand=sqrt(pow(I[a],2)+pow(Q[b],2));
sum=sum+powand;
}
p[i]=sum/(1.0*NumData); //信号平均强度
printf("data%d小区信号强度是%lf\n",g,p[i]);
printf("计算data%d的相关\n",g);
for(s=0;s<PssNum;s++) //计算滑动相关
{
z_I[i][s]=0;
z_Q[i][s]=0;
for(k=0;k<NumData-NumPdata;k++)
{
for(t=0,x=k;t<NumPdata;t++)
{
z_I[i][s]=z_I[i][s]+Pss_I[s][t]*I[t+k]-Pss_Q[s][t]*Q[t+k]; //结果的实部
z_Q[i][s]=z_Q[i][s]+Pss_I[s][t]*Q[t+k]+Pss_Q[s][t]*I[t+k]; //结果的虚部
}
z[k]=sqrt(pow(z_I[i][s],2)+pow(z_Q[i][s],2));
sum2aveR[i][s]+=z[k];
}
for(k=0;k<NumData-NumPdata;k++) //找出每一个PSS里面最大的相关
{
if(z[k]>max[i][s])
{
max[i][s]=z[k];
}
}
sum2aveR[i][s]=sum2aveR[i][s]/((NumData-NumPdata)*1.0);
printf("data%d小区与PSS%d的相关=%lf,以及平均相关=%lf\n",g,s,max[i][s],sum2aveR[i][s]);
}
for(s=0;s<PssNum;s++) //找出与小区相关最大的PSS
{
if(max[i][s]>relevant[i])
{
relevant[i]=max[i][s];
Pss_Max[i]=s;
}
}
printf("data%d小区与PSS%d相关最大=%lf\n",g,Pss_Max[i],relevant[i]);
fclose(fp); //关闭文件
}
}
/**************************************************************************
* @brief : 信号强度排序
* @param[in] : Sa指向用于小区信号强度排序数组首地址 ;Sb指向小区的信号强度数组首地址;
CellNum为小区数目
* @param[out] : None
* @return : None
* @others : None
***************************************************************************/
void Sort(double *Sa,double *Sb,int CellNum)
{
for(i=0;i<CellNum;i++) //存储信号强度用于排序
{
*(Sa+i)=*(Sb+i);
}
for(i=0;i<CellNum-1;i++) //冒泡排序
{
for(j=0;j<CellNum-1-i;j++)
{
if(*(Sa+j)<*(Sa+j+1))
{
temp=*(Sa+j);
*(Sa+j)=*(Sa+j+1);
*(Sa+j+1)=temp;
}
}
}
printf("\n");
}
/**************************************************************************
* @brief : 打印信号强度排序
* @param[in] : PSa指向用于小区信号强度排序数组首地址 ;Psb指向小区的信号强度数组首地址;
PSc指向存储小区区号数组首地址;CellNum为小区数目;
* @param[out] : None
* @return : None
* @others : None
***************************************************************************/
void PrintSort(double *PSa,double *PSb,int *PSc,int CellNum)
{
printf("12个小区信号强度排名从大到小如下(包含21和27):\n");
for(i=0;i<CellNum;i++)//对小区进行排序
{
for(j=0;j<CellNum;j++)
{
if(fabs(*(PSa+i)-*(PSb+j))<EPS)
break;
}
*(PSc+i)=j+20;
printf("data%d小区:%lf\n",*(PSc+i),*(PSa+i));
}
}
/**************************************************************************
* @brief : 主函数
* @param[in] : None
* @param[out] : None
* @return : None
* @others : None
***************************************************************************/
void main()
{
//输入文本长度
printf("How much cell and PSS there? \n");
scanf("%d",&CellNum);
scanf("%d",&PssNum);
//计算开辟空间数量
NumData=AutoCntLen(CellNum,1);
NumPdata=AutoCntLen(PssNum,0);
//内存开辟
double* p=(double*)calloc(CellNum,sizeof(double)); //小区的信号强度
double* sort=(double*)calloc(CellNum,sizeof(double)); //用于小区信号强度排序
double* relevant=(double*)calloc(CellNum,sizeof(double)); //存储每个小区的最大相关
int* Pss_Max=(int*)calloc(CellNum,sizeof(int)); //存储与每个小区最大相关的下标
int* top=(int*)calloc(CellNum,sizeof(int)); //用于信号排序
double* I=(double*)calloc(NumData,sizeof(double)); //存储小区I路信号
double* Q=(double*)calloc(NumData,sizeof(double)); //存储小区Q路信号
double* z=(double*)calloc(NumData-NumPdata,sizeof(double)); //存储小区与PSS的滑动相关
double **Pss_I=AllocateandInit(PssNum,NumPdata); //存储PSS的I路信号
double **Pss_Q=AllocateandInit(PssNum,NumPdata); //存储PSS的Q路信号
double **z_I=AllocateandInit(CellNum,PssNum); //存储每次滑动相关的I路信号
double **z_Q=AllocateandInit(CellNum,PssNum); //存储每次滑动相关的Q路信号
double **max=AllocateandInit(CellNum,PssNum); //存储每个小区与每个PSS相关后的最大相关
double **sum2aveR=AllocateandInit(CellNum,PssNum); //存储每个小区与每个PSS相关后的平均相关
//子函数调用
ReadPssData(Pss_I,Pss_Q,PssNum,NumPdata);
ReadData(I,Q,CellNum,PssNum,NumData,NumPdata,p,z_I,z_Q,Pss_I,Pss_Q,z,max,sum2aveR,relevant,Pss_Max);
Sort(sort,p,CellNum);
PrintSort(sort,p,top,CellNum);
//内存释放
FreeMemory(Pss_I,PssNum);
FreeMemory(Pss_Q,PssNum);
FreeMemory(z_I,CellNum);
FreeMemory(z_Q,CellNum);
FreeMemory(max,CellNum);
FreeMemory(sum2aveR,CellNum);
free(p);
free(sort);
free(relevant);
free(Pss_Max);
free(top);
free(I);
free(Q);
free(z);
//注意:指针一定要赋值为NULL,因为释放内存后,指针还有指向那块空间的地址,赋值为空防止二次访问报错
p=NULL;
sort=NULL;
relevant=NULL;
Pss_Max=NULL;
top=NULL;
I=NULL;
Q=NULL;
z=NULL;
}
四、Matlab滑动相关仿真
close all;
clear all;
for i=20:31
data=load(['C:\\Users\\86185\\Desktop\\通软实验\\180308204701120_第一次实验数据\\第一次实验数据\\data',num2str(i),'.txt']);
for j=0:2
PSS= load(['C:\\Users\\86185\\Desktop\\通软实验\\180308204701120_第一次实验数据\\第一次实验数据\\PSS',num2str(j),'.txt']);
[m,n]=size(data);
[m1,n1]=size(PSS);
PSS = padarray(PSS, [m-m1 0], 0, 'post');
[correlation1, lags1] = xcorr(data((1: 2: end),1), PSS((1: 2: end),1),m1/2);%对自同步信号I路填充
[correlation2, lags2] = xcorr(data((2: 2: end),1), PSS((2: 2: end),1),m1/2);%对自同步信号Q路填充
figure;
subplot(3,2,1);
plot(data((1: 2: end),1));
xlabel(['data',num2str(i),'I路信号量']);
ylabel(['data',num2str(i),'I路信号强度']);
subplot(3,2,2);
plot(data((2: 2:end),1));
xlabel(['data',num2str(i),'Q路信号量']);
ylabel(['data',num2str(i),'Q路信号强度']);
subplot(3,2,3);
plot(PSS((1: 2: m1),1));
xlabel(['PSS',num2str(j),'I路信号量']);
ylabel(['PSS',num2str(j),'I路信号强度']);
subplot(3,2,4);
plot(PSS((2: 2: m1),1));
xlabel(['PSS',num2str(j),'Q路信号量']);
ylabel(['PSS',num2str(j),'Q路信号强度']);
subplot(3,2,5);
plot(lags1, correlation1);
xlabel('滞后');
ylabel('I路相关性');
title(['I路相关性分析']);
subplot(3,2,6);
plot(lags2, correlation2);
xlabel('滞后');
ylabel('Q路相关性');
title(['Q路相关性分析']);
clear PSS;
end
clear data;
end
五、附录
1.C代码实现结果:
图 2
图 3
图 4
图 5
图 6
2. Matlab仿真结果:
由于该结果图过多,且不支持上传.emf文件,鄙人在这里就不贴图了,大家可以根据我写的代码自己跑一下结果图,实在不济,私信我,发给大家
3.调整文本大小后运行结果:
鄙人选取了data21的文本数据给大家展示,大家可以发现原来文本长度是30000行,鄙人手动模拟填充100行数据,相当于每路数据增加了50个,可能大家会问为什么不追加更多呢?因为本实验假设的是文本长度相差不大,根据文本最大长度进行动态内存开辟,且calloc为赋初值0。但对于文本长度较短的小区数据,无论是对data21填充5000行数据还是填充100行数据,计算其他小区信号时平均信号强度会降低,所以鄙人修改了一下代码,通过信号总强度去进行观察。
图 7
图 8
p[i]=sum/(1.0*NumData);
将上面这行代码,调整为下面这行代码
p[i]=sum;
图 9
图 10
上面两个结果图能够明显看到该代码可以根据文本长度进行动态内存开辟,但鄙人这里实现有点问题,因为当调整完一个小区的数据后,其他小区的信号强度也会随机改变,不清楚是不是存在内存覆盖,或者浮点数精度导致累计求和出现的问题。我较为相信是后者导致,希望大家跟我一起探讨。
4.C代码基础实现:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define M 20
#define EPS 1e-7
int i,j,k,h,s,t;
int a,b; //实部、虚部index
double temp; //用于冒泡排序
double sum;
int top[12]; //用于信号强度排序
char filename[M]; //创建文件名存储数组
double I[15000]; //实部
double Q[15000]; //虚部
double n=15000;
double p[12]; //12个小区的信号强度
double sort[12]; //用于排序的12个小区
double Pss_I[3][2048]; //确定信号的I路数据
double Pss_Q[3][2048]; //确定信号的Q路数据
double z_I[12][3]; //12个小区与3个pss的相关,I路
double z_Q[12][3]; //12个小区与3个pss的相关,Q路
double z[12952]; //12个小区与3个pss的相关
double max[12][3]={0}; //存储每个小区与每个PSS的相关
double sum2aveR[12][3]; //存储每个小区与每个PSS的平均相关
double relevant[12]={0}; //存储每个小区的最大相关
int Pss_Max[12]; //存储最大相关的下标
FILE *fp; //创建文件指针
void ReadPssData()
{
printf("读取PSS数据\n");
for(s=0;s<3;s++)
{
printf("正在读取pss%d的数据\n",s);
sprintf(filename,"C:\\Users\\86185\\Desktop\\通软实验\\180308204701120_第一次实验数据\\第一次实验数据\\PSS%d.txt",s);
if((fp=fopen(filename,"rt"))==NULL)
{
printf("Fail to open file!");
exit(0);
}
for(t=0,j=0,h=0;t<4096;t++)
{
if(t%2==0)
{
fscanf(fp,"%lf",&Pss_I[s][j]);
j++;
}
else
{
fscanf(fp,"%lf",&Pss_Q[s][h]);
h++;
}
}
fclose(fp); //关闭文件
}
printf("PSS数据读取完成\n");
}
void ReadData()
{
for(i=0;i<12;i++)
{
sprintf(filename,"C:\\Users\\86185\\Desktop\\通软实验\\180308204701120_第一次实验数据\\第一次实验数据\\data%d.txt",i+20);
if ( (fp = fopen(filename, "rt")) == NULL )
{
puts("Fail to open file!");
exit(0); //判断文件是否打开失败
}
sum=0;
double data[30000]={0};
printf("\n");
printf("正在读取data%d小区...\n",i+20);
for(t=0;t<30000;t++) //读取小区数据
{
fscanf(fp,"%lf",&data[t]);
}
printf("计算data%d小区信号强度...\n",i);
for(j=0,h=1,a=0,b=0;j<=29999;j+=2,h+=2,a++,b++) //计算信号总强度
{
I[a]=data[j];
Q[b]=data[h];
sum+=sqrt(pow(I[a],2)+pow(Q[b],2));
}
p[i]=sum/n; //信号平均强度
printf("data%d小区信号强度是%lf\n:",i+20,p[i]);
printf("计算data%d的相关\n",i+20);
for(s=0;s<3;s++) //计算滑动相关
{
z_I[i][s]=0;
z_Q[i][s]=0;
for(k=0;k<15000-2048;k++)
{
for(t=0;t<2048;t++)
{
z_I[i][s]=z_I[i][s]+Pss_I[s][t]*I[t+k]-Pss_Q[s][t]*Q[t+k];//结果的实部
z_Q[i][s]=z_Q[i][s]+Pss_I[s][t]*Q[t+k]+Pss_Q[s][t]*I[t+k];//结果的虚部
}
z[k]=sqrt(pow(z_I[i][s],2)+pow(z_Q[i][s],2));
sum2aveR[i][s]+=z[k];
}
for(k=0;k<15000-2048;k++) //找出每一个PSS里面最大的相关
{
if(z[k]>max[i][s])
{
max[i][s]=z[k];
}
}
sum2aveR[i][s]=sum2aveR[i][s]/12952.0;
printf("data%d小区与PSS%d的相关=%lf,以及平均相关=%lf\n",i+20,s,max[i][s],sum2aveR[i][s]);
}
for(s=0;s<3;s++) //找出与小区相关最大的PSS
{
if(max[i][s]>relevant[i])
{
relevant[i]=max[i][s];
Pss_Max[i]=s;
}
}
printf("data%d小区与PSS%d相关最大=%lf\n",i+20,Pss_Max[i],relevant[i]);
fclose(fp); //关闭文件
}
}
void Sort(double *a,double *b)
{
for(i=0;i<12;i++) //存储信号强度用于排序
{
*(a+i)=*(b+i);
}
for(i=0;i<11;i++) //冒泡排序
{
for(j=0;j<11-i;j++)
{
if(*(a+j)<*(a+j+1))
{
temp=*(a+j);
*(a+j)=*(a+j+1);
*(a+j+1)=temp;
}
}
}
printf("\n");
}
void PrintSort(double *a,double *b,int *c)
{
printf("12个小区信号强度排名从大到小如下(包含21和27):\n");
for(i=0;i<12;i++)//对小区进行排序
{
for(j=0;j<12;j++)
{
if(fabs(*(a+i)-*(b+j))<EPS)
break;
}
*(c+i)=j+20;
printf("data%d小区:%lf\n",*(c+i),*(a+i));
}
}
int main()
{
ReadPssData();
ReadData();
Sort(sort,p);
PrintSort(sort,p,top);
return 0;
}
5.从基础到动态分配之间是如何跨越
(1)基础实现难点存在于两个地方:
①文件处理阶段:
采用sprintf函数将文件地址存储到文件名字符数组filename当中,通过rt读取文本文件方式打开文件
②滑动相关阶段:
鄙人用示意图形式来方便大家直观理解
图 11
(2)100%动态内存分配实现:
①采用calloc:
相较于基础实现鄙人做了较多技术调整,大家可以直观的看到数组实现了动态地址的分配,采用较多的动态内存分配函数是calloc,因为分配的地址空间过大,需要进行一定的初始化,尽可能地避免出现数据异常的情况。
②特别说明二维数组的动态地址分配:
array 的类型是double**,也就是指向指针的指针。array 是一个指针,指向一个double*类型的数组。这个数组中的每个元素都是指向double类型的指针。上面的代码中分别在给列分配内存时采用的两种方式,一种可以实现内存的连续分配,另一种则可能造成空间不连续。
方式1:
通过下面一行代码实现从array[0]连续开辟一个存储double类型的内存,可以结合示意图来看
*array = calloc(rows * cols, sizeof(double));
图 12
方式2:
跟方式一主要区别在于没有通过array[0]指向的位置,去开辟内存。每一行的内存分配是独立进行的,而不是一次性分配整个二维数组的内存块。具体来说,当使用循环为每一行分配内存时,每次calloc 都会在堆内存中找到一块足够大小的空闲内存块,这些内存块的位置可能是不连续的,尤其是在存在内存碎片的情况下,从而可能造成内存不连续。可结合示意图来看
array[i] = (double*)calloc(cols,sizeof(double));
图 13