C矩阵结构

C矩阵结构,c,arrays,matrix,segmentation-fault,structure,C,Arrays,Matrix,Segmentation Fault,Structure,我正在学习C语言,因为我遇到了一个分段错误,所以很难确定我做错了什么。 我试图初始化一个矩阵结构,它包含一个指向具有实际数据的2D数组的指针。然后用数组中的数据填充并打印 #include "base.h" struct Matrix { int rows; // number of rows int cols; // number of columns double** data; // a pointer to an array of n_rows pointer

我正在学习C语言,因为我遇到了一个分段错误,所以很难确定我做错了什么。 我试图初始化一个矩阵结构,它包含一个指向具有实际数据的2D数组的指针。然后用数组中的数据填充并打印

#include "base.h" 

struct Matrix {
    int rows; // number of rows
    int cols; // number of columns
    double** data; // a pointer to an array of n_rows pointers to rows
};
typedef struct Matrix Matrix;

Matrix* make_matrix(int n_rows, int n_cols) {
    struct Matrix matrix;
    matrix.rows = n_rows;
    matrix.cols = n_cols;
    matrix.data = (double**)malloc(sizeof(double*) * n_rows);
    for(int x = 0; x < n_rows; x++){
        matrix.data[x] = (double*)calloc(n_cols, sizeof(double));
    }
    struct Matrix *m;
    m = &matrix;
    return m;
}

Matrix* copy_matrix(double* data, int n_rows, int n_cols) {
    struct Matrix *matrix = make_matrix(n_rows, n_cols);
    for(int x = 0; x < n_rows; x++) {
        for(int y = 0; y < n_cols; y++) {
            matrix->data[x][y] = data[x+y];
        }
    }
    return matrix;
}

void print_matrix(Matrix* m) {
    for(int x = 0; x < m->rows; x++) {
        for(int y = 0; y < m->cols; y++) {
            printf("%f", m->data[x][y]);
        }
    }
}

void matrix_test(void) {

    double a[] = { 
        1, 2, 3, 
        4, 5, 6, 
        7, 8, 9 };
    Matrix* m1 = copy_matrix(a, 3, 3);
    print_matrix(m1);
}

int main(void) {
    base_init();
    base_set_memory_check(true);
    matrix_test();
    return 0;
}
#包括“base.h”
结构矩阵{
int rows;//行数
int cols;//列数
double**data;//指向n_行数组的指针指向行的指针
};
类型定义结构矩阵;
矩阵*make_矩阵(int n_行,int n_列){
结构矩阵;
matrix.rows=n_行;
matrix.cols=n_cols;
matrix.data=(double**)malloc(sizeof(double*)*n行);
对于(int x=0;x数据[x][y]=数据[x+y];
}
}
收益矩阵;
}
无效打印矩阵(矩阵*m){
对于(int x=0;xrows;x++){
对于(int y=0;ycols;y++){
printf(“%f”,m->data[x][y]);
}
}
}
空隙矩阵_试验(空隙){
双a[]={
1, 2, 3, 
4, 5, 6, 
7, 8, 9 };
矩阵*m1=复制_矩阵(a,3,3);
打印矩阵(m1);
}
内部主(空){
base_init();
基本设置内存检查(真);
矩阵_检验();
返回0;
}
此外,除了分段故障触发错误之外,还有什么可以改进的地方?

以下内容:

Matrix* make_matrix(int n_rows, int n_cols) {
    struct Matrix matrix;
matrix
声明为函数
make_matrix()
中的局部变量。在函数的末尾,取局部变量的地址,出于某种原因将其存储在指针中,然后返回该指针。因此,您将返回一个指针,该指针指向函数堆栈中的某个位置。但是函数刚刚返回,因此该位置现在无效


而不是
struct矩阵您需要执行
Matrix*m=malloc(sizeof(Matrix))(如果编译器不允许这样做,请尝试
Matrix*m;m=malloc(sizeof(Matrix));
)然后继续按如下方式填充结构:
m->rows=n\u rows等。

欢迎来到C。这里有两个大问题:

1) 无法返回指向函数局部变量的指针。(与
make_matrix()
中的错误相关)

2) 在C语言中没有明显的方法来定义“多维”数组,在这里您可以方便地访问像
data[x][y]
这样的元素,除非您的行大小在编译时已知并固定。(并且在编译时您的矩阵维度是未知的。)

让我们分开处理

要解决1),在
make_matrix()
中要做的实际上是:

Matrix* make_matrix(int n_rows, int n_cols) {
    struct Matrix* pmatrix = malloc(sizeof(struct Matrix));
    pmatrix->rows = n_rows;
    pmatrix->cols = n_cols;
    ...
    ...
    return pmatrix;
}
但单凭这一点并不能解决这个问题。数据需要存储在一个大的
cols
*
元素数组中,您需要指定如何定位每个项目,而不是
数据[x][y]

所以要解决2),矩阵结构定义应该是

struct Matrix {
    int rows; // number of rows
    int cols; // number of columns
    double* data; // <- note that this is a pointer to one dim array
};
这就是你现在所需要的

要复制相同尺寸和格式的矩阵

Matrix* copy_matrix(double* data, int n_rows, int n_cols) {
    struct Matrix *matrix = make_matrix(n_rows, n_cols);
    for(int i = 0; i < n_rows*n_cols; i++)
        matrix->data[i] = data[i];
    return matrix;
}

当然,您需要正确地检查malloc()返回的错误并正确地清理。

谢谢您的回答,我已经了解了失败的地方。 为了完整起见,工作代码如下所示:

#include "base.h"

struct Matrix {
    int rows; // number of rows
    int cols; // number of columns
    double** data; // a pointer to an array of n_rows pointers to rows; a row is an array of n_cols doubles 
};
typedef struct Matrix Matrix;

Matrix* make_matrix(int n_rows, int n_cols) {
    struct Matrix* matrix = malloc(sizeof(Matrix));
    matrix->rows = n_rows;
    matrix->cols = n_cols;
    double** data = malloc(sizeof(double*) * n_rows); 
    for(int x = 0; x < n_rows; x++){
        data[x] = calloc(n_cols, sizeof(double));
    }
    matrix->data = data;
    return matrix;
}

Matrix* copy_matrix(double* data, int n_rows, int n_cols) {
    struct Matrix *matrix = make_matrix(n_rows, n_cols);
    for(int x = 0; x < n_rows; x++) {
        for(int y = 0; y < n_cols; y++) {
            matrix->data[x][y] = data[n_cols*x+y];
        }
    }
    return matrix;    
}

void print_matrix(Matrix* m) {
    for(int x = 0; x < m->rows; x++) {
        printf("%s", "\n");
        for(int y = 0; y < m->cols; y++) {
            printf("%f\t", m->data[x][y]);
        }
    }
}

void matrix_test(void) {   

    double a[] = { 
        1, 2, 3, 
        4, 5, 6, 
        7, 8, 9,
        10,11,12
        };
    Matrix* m1 = copy_matrix(a, 4, 3);
    print_matrix(m1);
}

int main(void) {
    base_init();
    base_set_memory_check(true);
    matrix_test();
    return 0;
}
#包括“base.h”
结构矩阵{
int rows;//行数
int cols;//列数
double**data;//指向n_行数组的指针指向行;行是n_cols double的数组
};
类型定义结构矩阵;
矩阵*make_矩阵(int n_行,int n_列){
结构矩阵*矩阵=malloc(sizeof(矩阵));
矩阵->行=n_行;
矩阵->列=n_列;
double**data=malloc(sizeof(double*)*n行);
对于(int x=0;x数据=数据;
收益矩阵;
}
矩阵*复制矩阵(双*数据,整数n行,整数n列){
结构矩阵*矩阵=生成矩阵(n行,n列);
对于(int x=0;x数据[x][y]=数据[n_cols*x+y];
}
}
收益矩阵;
}
无效打印矩阵(矩阵*m){
对于(int x=0;xrows;x++){
printf(“%s”,“\n”);
对于(int y=0;ycols;y++){
printf(“%f\t”,m->data[x][y]);
}
}
}
空隙矩阵_检验(空隙){
双a[]={
1, 2, 3, 
4, 5, 6, 
7, 8, 9,
10,11,12
};
矩阵*m1=复制矩阵(a,4,3);
打印矩阵(m1);
}
内部主(空){
base_init();
基本设置内存检查(真);
矩阵_检验();
返回0;
}

如果有更多的改进需要进行,或者您脑海中浮现的惯例受到影响,请告诉我。

您正在返回一个指向局部变量
矩阵的指针。
。您的代码不包含指向2D数组的指针
double*
不是二维数组,不能表示二维数组,
double**
也不是指向二维数组的指针。一般情况下,不要强制转换
malloc
&friends或
void*
的结果。请参阅。或使用静态变量。另一种方法是按值返回
矩阵
:除
矩阵make_Matrix(…){……;return Matrix;}
(丢失
矩阵*m=&Matrix;
)之外的代码与现在一样。该结构足够小,因此返回整个结构的副本不会有问题。@toster cx:不!然后,在复制之前,一次只能有一个
矩阵->
矩阵->数据[x][y]=数据[n_行*x+y]@toster cx:也许我不该上钩,但那是马克
printf("%f ", m->data[x*(m->cols) + y]);
#include "base.h"

struct Matrix {
    int rows; // number of rows
    int cols; // number of columns
    double** data; // a pointer to an array of n_rows pointers to rows; a row is an array of n_cols doubles 
};
typedef struct Matrix Matrix;

Matrix* make_matrix(int n_rows, int n_cols) {
    struct Matrix* matrix = malloc(sizeof(Matrix));
    matrix->rows = n_rows;
    matrix->cols = n_cols;
    double** data = malloc(sizeof(double*) * n_rows); 
    for(int x = 0; x < n_rows; x++){
        data[x] = calloc(n_cols, sizeof(double));
    }
    matrix->data = data;
    return matrix;
}

Matrix* copy_matrix(double* data, int n_rows, int n_cols) {
    struct Matrix *matrix = make_matrix(n_rows, n_cols);
    for(int x = 0; x < n_rows; x++) {
        for(int y = 0; y < n_cols; y++) {
            matrix->data[x][y] = data[n_cols*x+y];
        }
    }
    return matrix;    
}

void print_matrix(Matrix* m) {
    for(int x = 0; x < m->rows; x++) {
        printf("%s", "\n");
        for(int y = 0; y < m->cols; y++) {
            printf("%f\t", m->data[x][y]);
        }
    }
}

void matrix_test(void) {   

    double a[] = { 
        1, 2, 3, 
        4, 5, 6, 
        7, 8, 9,
        10,11,12
        };
    Matrix* m1 = copy_matrix(a, 4, 3);
    print_matrix(m1);
}

int main(void) {
    base_init();
    base_set_memory_check(true);
    matrix_test();
    return 0;
}