我正在阅读MESCHACH库的源代码,用于矩阵和向量计算。以下是库中使用的数据结构:
/* matrix definition */
typedef struct {
unsigned int m, n;
unsigned int max_m, max_n, max_size;
Real **me,*base; /* base is base of alloc'd mem */
} MAT;
在这里,*base
在结构中的用途是什么?我的意思是**me
是包含矩阵的值,而上面的值包含其维度,base
包含的内容。
为矩阵分配内存的代码:
MAT *m_get(int m, int n)
{
MAT *matrix;
int i;
if (m < 0 || n < 0)
error(E_NEG,"m_get");
if ((matrix=NEW(MAT)) == (MAT *)NULL )
error(E_MEM,"m_get");
else if (mem_info_is_on()) {
mem_bytes(TYPE_MAT,0,sizeof(MAT));
mem_numvar(TYPE_MAT,1);
}
matrix->m = m; matrix->n = matrix->max_n = n;
matrix->max_m = m; matrix->max_size = m*n;
#ifndef SEGMENTED
if ((matrix->base = NEW_A(m*n,Real)) == (Real *)NULL )
{
free(matrix);
error(E_MEM,"m_get");
}
else if (mem_info_is_on()) {
mem_bytes(TYPE_MAT,0,m*n*sizeof(Real));
}
#else
matrix->base = (Real *)NULL;
#endif
if ((matrix->me = (Real **)calloc(m,sizeof(Real *))) ==
(Real **)NULL )
{ free(matrix->base); free(matrix);
error(E_MEM,"m_get");
}
else if (mem_info_is_on()) {
mem_bytes(TYPE_MAT,0,m*sizeof(Real *));
}
#ifndef SEGMENTED
/* set up pointers */
for ( i=0; i<m; i++ )
matrix->me[i] = &(matrix->base[i*n]);
#else
for ( i = 0; i < m; i++ )
if ( (matrix->me[i]=NEW_A(n,Real)) == (Real *)NULL )
error(E_MEM,"m_get");
else if (mem_info_is_on()) {
mem_bytes(TYPE_MAT,0,n*sizeof(Real));
}
#endif
return (matrix);
}
为什么他们首先分配基数并使用它来分配me
?另外,如果您已阅读源代码,请告诉我在此库中使用SEGMENTED。声明在configure
文件中。
矩阵结构在matrix.h
中定义,m_get()在memory.c
中。
答案 0 :(得分:2)
如果我正确读取代码,me
是指向&#34;行&#34;的开头的一维指针数组。在矩阵中:matrix->me[i] = &(matrix->base[i*n]);
使用索引i
处相应行的地址填充数组。
这使得可以将me
与两个索引一起使用,就好像它确实是一个二维数组,例如写double d = myMatrix.me[row][column];
。当然,sizeof(myMatrix.me)
或取me
个元素的地址的行为与正确的二维数组的行为不同。
如果定义了 SEGMENTED
,矩阵中的内存将逐行分配,并且不会连续(并且base
将为null)。如果要将原始的二维数组传递给不知道MAT
类型的库,则元素将需要在内存中连续存在。如果你只是正常索引它并不重要。
顺便说一句(我知道这是来自图书馆的代码,但仍然存在):很有趣,就在今天,我被Jens Gustedt https://stackoverflow.com/a/12805980/3150802引导到这个问题的有趣解决方案。他使用C99功能,可变长度数组。有趣的是,他实际上并没有创建任何可变长度数组(相反,他只是像你的矩阵类一样使用malloc),而只是在声明中使用运行时长度。非常有趣。他的帖子中的A
在你的矩阵类中扮演me
的角色,即它是指向一维数组的指针,可以将其索引两次以从矩阵中获得单个数字。 / p>