存储具有可变2D阵列的结构数组

时间:2015-08-28 15:22:39

标签: c arrays struct

简要说明:如果你想测试代码,你可以在GitHub上找到Gist: https://gist.github.com/nok/c0ff77db0513384fcbbd

我们有一套已知的论文。类型Paper的每篇论文都有Matrix类型的x矩阵。我们想要动态存储一系列论文并从其他函数中读取这些论文。这是数据结构:

typedef struct Matrix {
    int         rows;
    int         cols;
    float**     data;
} Matrix;

typedef struct Page {
    char        id;         // unique id
    int         size;       // size of matrices
    Matrix**    matrices;
} Page;

我们使用以下函数创建了必需的结构(删除了错误处理):

Matrix *new_matrix(int n_rows, int n_cols, float** data)
{
    Matrix *M = (Matrix *) malloc(sizeof(Matrix));
    M->rows = n_rows;
    M->cols = n_cols;
    M->data = (float **) malloc(M->rows * sizeof(float *));
    int i;
    for (i = 0; i < M->rows; i++) {
        M->data[i] = data[i];
    }
    return M;
};

Page *new_page(int id, int n_size, Matrix** data)
{
    Page *P = (Page *) malloc(sizeof(Page));
    P->id = id;
    P->size = n_size;
    int i;
    P->matrices = malloc(n_size * sizeof(Matrix));
    for (i = 0; i < n_size; ++i) {
        P->matrices[i] = data[i];
    }
    return P;
};

现在,我们想要在单独的函数app_init中分配内存:

Page **pages;       // <--------------

int main(void) {

    app_init();
    app_update();

    return EXIT_SUCCESS;
}

void app_init() {
    pages = (Page **) malloc(2 * sizeof(Page *));

    Matrix* m1 = new_matrix(3, 5, (float*[5]) {
        (float[5]) { 111, 112, 113, 114, 115 },
        (float[5]) { 121, 122, 123, 124, 125 },
        (float[5]) { 131, 132, 133, 134, 135 },
    });
    Matrix* m2 = new_matrix(3, 4, (float*[4]) {
        (float[4]) { 211, 212, 213, 214 },
        (float[4]) { 221, 222, 223, 224 },
        (float[4]) { 231, 232, 233, 234 },
    });
    pages[0] = (Page *) new_page(1, 2, (Matrix*[2] ) { m1, m2 });

    Matrix* m3 = new_matrix(3, 5, (float*[5]) {
        (float[5]) { 311, 312, 313, 314, 315 },
        (float[5]) { 321, 322, 323, 324, 325 },
        (float[5]) { 331, 332, 333, 334, 335 },
    });
    Matrix* m4 = new_matrix(3, 4, (float*[4]) {
        (float[4]) { 411, 412, 413, 414 },
        (float[4]) { 421, 422, 423, 424 },
        (float[4]) { 431, 432, 433, 434 },
    });
    pages[1] = (Page *) new_page(2, 2, (Matrix*[2] ) { m3, m4 });
}

(我想在变量pages中存储所有页面时会出现问题。)
然后我们想查看所有论文的所有矩阵:

void app_update() {
    int i, j;
    for (i=0; i<NUMBER_PAGES; i++){
        printf("Page (%d): %d\n", i, pages[i]->id);
        for(j=0; j<pages[i]->size; j++){
            printf("Matrix (%d):\n", j);
            print_matrix(
                    pages[i]->matrices[j]->rows,
                    pages[i]->matrices[j]->cols,
                    (float *)pages[i]->matrices[j]->data[0]);
            printf("\n---\n");
        }
        printf("\n------\n");
    }
}

void print_matrix(int row, int col, float* data) {
    int i, j;
    for (i=0; i<row; i++){
        for(j=0; j<col; j++){
            printf("%.3f ", data[i*col+j]);
        }
        printf("\n");
    }
}

阅读pages的值在app_init()范围内有效。但是在main()app_update()的范围内,它失败了。我们如何永久存储这些值?

1 个答案:

答案 0 :(得分:0)

app_init()中传递给new_matrix()的复合文字具有自动存储功能,app_init()返回后将不再有效。因此,Matrix类型中的指针将指向无效数据。

另外,传递给new_page()的复合文字是非常量的,所以不是真正的文字。这是GCC扩展,不是C99语言的一部分。

此外,您的print_matrix()函数将data视为指向rows * cols float的连续块的指针,但您的Matrix类型包含连续的指向rows cols s的连续块的float指针块。

我建议您将data类型的Matrix成员和data的{​​{1}}参数更改为new_matrix()类型,更改{{1分配float* malloc的连续块,并将M->rows * M->cols指针中的float M->rows * M->cols复制到float。您需要将对data的调用中的复合文字更改为M->data的二维数组。实际上,您可能需要将其设置为1维以匹配new_matrix()的参数,但您可以添加空格以使其显示为二维。