2014-12-07 2 views
0

Я пытаюсь сохранить ряд матриц в непрерывном блоке памяти, а затем восстановить их. Каждый массив будет иметь тот же размер (n x n).Хранение массива из 2d массивов в C

Насколько я понимаю, что мне нужно сделать, это:

  1. Выделяют и инициализировать каждый массив, мне нужно, чтобы сохранить/восстановить.

  2. Выделяют непрерывный блок памяти размером (# arrays) * sizeof (1 array) и присвоить указатель, ***matrices, к началу блока

  3. Скопируйте каждый массив в блок на matrices[0], matrices[1] ...

  4. Распечатайте их, отправив matrices[0], matrices[1] ... к matrix_print функции

Теперь, очевидно, я что-то недопонимаю, потому что он не работает. Это выход я получаю прямо перед он выходит из строя:

Matrix A is 16 bytes. 
Matrix B is 16 bytes. 
So, we will allocate 32 bytes in row_blocks. 
Matrix A: 
| 1 1 | 
| 2 2 | 
Matrix B: 
| 2 2 | 
| 

Вот код для моего теста, что я пытаюсь получить работу:

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 

void matrix_print(int dim, int ***matrix); 
void matrix_init(int dim, int matrix[dim][dim], int val); 

int main(int argc, char *argv[]) 
{ 
    int dim = 2; 

    int A[dim][dim], B[dim][dim]; 

    matrix_init(dim, A, 1); 
    matrix_init(dim, B, 2); 

    printf("Matrix A is %d bytes.\n", sizeof A); 
    printf("Matrix B is %d bytes.\n", sizeof B); 

    int ***matrices = malloc(sizeof A + sizeof B); 

    printf("So, we will allocate %d bytes in matrices.\n\n", 
      sizeof A + sizeof B); 

    memcpy(matrices[0], A, sizeof (A)); 
    memcpy(matrices[1], B, sizeof (B)); 

    printf("Matrix A:\n"); 
    matrix_print(dim, &matrices[0]); 
    printf("Matrix B:\n"); 
    matrix_print(dim, &matrices[1]); 

    return 0; 
} 

void matrix_print(int dim, int ***matrix) 
{ 
    for (int i = 0; i < dim; i++) { 
     printf("|"); 
     for (int j = 0; j < dim; j++) { 
      printf("%2d ", matrix[i][j]); 
     } 
     printf("|\n"); 
    } 
} 

void matrix_init(int dim, int matrix[dim][dim], int val) 
{ 
    for (int i = 0; i < dim; i++) { 
     for (int j = 0; j < dim; j++) { 
      matrix[i][j] = val; 
     } 
    } 
} 

ответ

3

Радость двумерных матриц C!

Когда вы передаете один одномерный массив int[dim] к функции, он распадается на указатель на его первый элемент, int * или int[], потеряв информацию о его размере в процессе.

Двумерный массив int[dim][dim] не разлагается в двойной указатель, int **, но в указатель на первый элемент ряда размера dim из целых чисел, int (*)[dim] или int[][dim]. То есть, потому что обработаны многомерные массивы постоянного размера строки; они реализуются как непрерывные блоки данных, где для вычисления индексов используется постоянный размер. (Constant здесь означает константу для всех строк и во всех матричных операций, как в вашем случае это значение может быть переменной в C99.)

Ваши матрицы типа int[dim][dim] не могут быть представлены в виде int **, так что вы должны настроить тип вашей матрицы массива:

int (*matrices)[dim][dim]; 

matrices = malloc(sizeof A + sizeof B); 

сигнатура вашей функции печати также изменяется:

void matrix_print(int dim, int matrix[dim][dim]) 
{ 
    for (int i = 0; i < dim; i++) { 
     printf("|"); 
     for (int j = 0; j < dim; j++) { 
      printf("%2d ", matrix[i][j]); 
     } 
     printf("|\n"); 
    } 
} 

И вы называете это так:

matrix_print(dim, matrices[0]); 

без адресаты оператора &.

Сноски:

  • int (*x)[dim] представляет собой указатель на массив целочисленных длины dim. int *x[dim] - это массив длины dim указателей на int.

  • Специальное обращение связано с тем, как Fortran хранит многомерные массивы, я думаю. Если, с другой стороны, вы выделили массив указателей, то они равны int **. Такие структуры данных могут содержать оборванные матрицы.

  • Матрицы представляют собой массивы типа C99 с переменной длиной (VLA), которые не могут быть инициализированы, поэтому malloc должен быть отдельным объявлением и присваиванием.

+0

Получил это, спасибо большое. Я на самом деле попробовал int '* matrices [dim] [dim]' раньше и запутался, потому что это не позволило бы VLA. Он работает с круглыми скобками, хотя 'int * (matrices) [dim] [dim]'! – Thomas

Смежные вопросы