关于使用 malloc
函数为矩阵分配内存空间,您有什么好的指示吗?
这些天我看到很多编码器在需要使用malloc
来管理它们时以“糟糕”的方式编码矩阵。我这样想是不是错了?
我指的“坏”代码示例如下:
int main()
{
char **row;
int width=80, height=24, i, j;
row = malloc(height * sizeof(char *));
for(i = 0; i < width; i++)
row[i] = malloc(width * sizeof(char));
for(i = 0; i < height; i++)
{
for(j = 0; j < width; j++)
{
row[i][j] = i*j;
}
}
return 0;
}
在上面的代码中我发现了至少三个问题:
它会严重破坏内存。
它使用了比必要更多的内存
它使用于矩阵的内存不连续。
有人建议我使用这种 C99 语法的有趣方式:
int (*matrix)[columns] = malloc(sizeof(int[rows][columns]));
现在我需要将这个变量矩阵传递给以下函数:
void print_matrix2(int **m,int r,int c)
{
int y,x;
for(y=0;y<r;y++) {
for(x=0;x<c;x++) {
printf("(%2d,%2d) = %04d; ",y+1,x+1,m[y][x]);
}
}
}
我发现的唯一方法是更改原型(prototype):
void print_matrix2(int (*m)[5],int r,int c);
但我想避免 [5] 声明,我希望能够向我的函数发送我想要的任意数量的列!
如果是这样,我觉得这个 C99 改进并不是解决问题的 final方法,我认为解决矩阵管理的最好和简单的方法是使用经典的 C 语言来管理它们!
最佳答案
使用malloc()
分配一个连续的内存块:
some_datatype_t* matrix = NULL;
matrix = malloc(nrows * ncols * sizeof(some_datatype_t));
if (!matrix) {
perror("malloc failed");
exit(ENOMEM);
}
编写一个取消引用单元格的函数:
some_datatype_t
get_value_from_matrix_at_index_ij(some_datatype_t* mtx,
uint32_t ncols,
uint32_t i,
uint32_t j)
{
return mtx[i + i * (ncols - 1) + j];
}
或者二传手:
void
set_value_for_matrix_at_index_ij(some_datatype_t** mtx_ptr,
uint32_t ncols,
uint32_t i,
uint32_t j,
some_datatype_t val)
{
*mtx_ptr[i + i * (ncols - 1) + j] = val;
}
不要忘记 free()
矩阵:
free(matrix), matrix = NULL;
这是一个 3x4 矩阵的示例:
0 1 2 3
------------
0 | 0 1 2 3
1 | 4 5 6 7
2 | 8 9 10 11
它有 3 行和 4 列(ncols
= 4
)。
在线性化形式中,其单元格如下所示:
0 1 2 3 4 5 6 7 8 9 10 11
要在某个零索引行 i
和列 j
处查找单元格的内容,您可以在常数时间内计算索引或地址以取消引用:
{1, 2} = matrix[1 + 1*3 + 2] = matrix[6]
{2, 3} = matrix[2 + 2*3 + 3] = matrix[11]
etc.
如果您想将一些有用的属性隐藏到一个干净的包中,您甚至可以将其中的大部分包装到一个 struct
中:
typedef struct matrix {
some_datatype_t* data;
uint32_t nrows;
uint32_t ncols;
} matrix_t;
然后您只需初始化并传递一个指向 matrix_t
变量的指针:
matrix_t*
init_matrix(uint32_t nrows, uint32_t ncols)
{
matrix_t *m = NULL;
m = malloc(sizeof(matrix_t));
if (!m) { /* error */ }
m->data = NULL;
m->data = malloc(nrows * ncols * sizeof(some_datatype_t));
if (!m->data) { /* error */ }
m->nrows = nrows;
m->ncols = ncols;
return m;
}
some_datatype_t
get_value_from_matrix_at_index_ij(matrix_t* mtx,
uint32_t i,
uint32_t j)
{
return mtx->data[i + i * (mtx->ncols - 1) + j];
}
void
set_value_for_matrix_at_index_ij(matrix_t** mtx_ptr,
uint32_t i,
uint32_t j,
some_datatype_t val)
{
(*mtx_ptr)->data[i + i * ((*mtx_ptr)->ncols - 1) + j] = val;
}
void
delete_matrix(matrix_t** m)
{
free((*m)->data), (*m)->data = NULL;
free(*m), *m = NULL;
}
如果您使用的是对称方阵,则可以利用对称性并使用一半的内存。有时,如果可以删除对角线的存储(例如,相关性或其他对称统计分数),则内存不到一半。
主要是,这里的想法是考虑如何编写一个映射矩阵索引对 (i, j)
和一些连续数组索引 k
之间的方程.
关于c - 我如何使用 malloc 在 C 中创建矩阵并避免内存问题?如何使用 C99 语法将矩阵传递给函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29981528/