编译并运行该函数后,我遇到了段错误:11.我相信应该正确执行malloc,所以不确定为什么会出现段错误。任何见解将不胜感激!
typedef struct matrix matrix;
struct matrix {
unsigned int n_rows;
unsigned int n_cols;
float **entries;
};
//refer to matrix.h
matrix *matrix_zero(unsigned int n_rows, unsigned int n_cols){
struct matrix* new = (struct matrix*)malloc(sizeof(struct matrix));
new->entries = malloc(n_rows * n_cols * sizeof(float));
new->n_rows=n_rows;
new->n_cols=n_cols;
for(int x = 0; x < n_rows; x++){
for(int y = 0; y < n_cols; y++){
new->entries[x][y] = 0;
}
}
return new;
}
/* main: run the evidence functions above */
int main(int argc, char *argv[])
{
struct matrix* test1 = matrix_zero(3,3);
// matrix_show(test1);
}
答案 0 :(得分:4)
问题似乎出在您为matrix->entries
分配的位置上。该结构定义了一个指向指针的指针,但是您要分配一个浮点指针float*
和float**
。您需要分配n_rows
号float*
,并且每个分配点都指向n_cols
号float
值的分配。例如:
int i;
// No error checking shown here
new->entries = malloc(sizeof(float*) * n_rows);
for (i = 0; i < n_rows; i++) {
new->entries[i] = malloc(sizeof(float) * n_cols);
}
答案 1 :(得分:0)
您已经为rows
分配了cols
大小的数组,但是编译器无法知道每一行的实际行大小,因此符号entries[i]
确实期望有一个指向简单浮点数组而不是二维数组的指针。这是与n维数组和C语言中的指针数组在结构上的主要区别之一。仅当完全限定数组维的大小(例如,将其声明为float entries[N][M];
时,编译器才知道如何为它定维- -看起来您不能在维度中使用变量表达式,只能使用静态编译时常量)
您在这里有两种方法:
使用一维数组并根据行大小计算索引:
typedef struct matrix matrix;
struct matrix {
unsigned int n_rows;
unsigned int n_cols;
float *entries; /* we make this to point to a single array of n_rows * n_cols entries */
};
new->entries = malloc(n_rows * n_cols * sizeof(float));
new->n_rows=n_rows;
new->n_cols=n_cols;
for(int x = 0; x < n_rows; x++){
for(int y = 0; y < n_cols; y++){
new->entries[x * n_cols + y] = 0.0; /* entry position should be as shown */
}
使用n_cols
个条目的单个行数组(这已经在@joel的另一个答案中显示了)
typedef struct matrix matrix;
struct matrix {
unsigned int n_rows;
unsigned int n_cols;
float **entries; /* this time the entries field points to an array of pointers to float. */
};
new->entries = malloc(n_rows * sizeof *new->entries); /* individual cells are 'float *', not 'float' this time. */
new->n_rows=n_rows;
new->n_cols=n_cols;
for(int x = 0; x < n_rows; x++){
new->entries[x] = malloc(n_cols* sizeof **new->entries); /* this time float *'s are here */
for(int y = 0; y < n_cols; y++){
new->entries[x][y] = 0; /* entry position should be as shown */
}
}
两种方法都有说明:
第一个方法仅需要一个malloc(3)
用于entrys数组,因此这使得分配和取消分配更加容易,但是某些实现可能会限制单个malloc(3)
的实际大小分配巨大的矩阵。这使得整个矩阵的重新分配也更加容易。
第二种方法仅需要n_rows
个指针的malloc和n_rows
n_cols
个float
的malloc。这样就可以分配庞大的矩阵(您永远不会将整个矩阵分配到一个块中),但是必须先分配所有行,然后再分配指向行的指针数组,然后再分配矩阵结构。
我建议您使用malloc(n_cols * sizeof *new->entries)
而不是malloc(n_cols * sizeof (float *))
,因此,如果您更改new->entries
的定义类型,则无需更改此表达式。
最后,认为C语言在调用函数方面没有魔力。您可能错误地假设使malloc( n_rows * n_cols * sizeof(float) )
自动将指针转换为二维数组,但是那里没有魔术,malloc(3)
是一个普通的C函数,就像您可以编写的那样,这就是为什么它需要实际的字节数,而不是数组的尺寸(以元素为单位)的原因。