2013-09-06 6 views
3

Я пытаюсь реализовать свою собственную базовую версию умножения матрицы в C и на основе другой реализации, я создал тип данных матрицы. Код работает, но, будучи новичком C, я не понимаю, почему.C: Инициализация динамического массива внутри структуры

Проблема: У меня есть структура с динамическим массивом внутри, и я инициализирую указатель. Смотрите ниже:

// Matrix data type 
typedef struct 
{ 
    int rows, columns;  // Number of rows and columns in the matrix 
    double *array;   // Matrix elements as a 1-D array 
} matrix_t, *matrix; 

// Create a new matrix with specified number of rows and columns 
// The matrix itself is still empty, however 
matrix new_matrix(int rows, int columns) 
{ 
    matrix M = malloc(sizeof(matrix_t) + sizeof(double) * rows * columns); 
    M->rows = rows; 
    M->columns = columns; 
    M->array = (double*)(M+1); // INITIALIZE POINTER 
    return M; 
} 

Почему мне нужно инициализировать массив (двойной *) (М + 1)? Кажется, что также (double *) (M + 100) работает нормально, но, например, (double *) (M + 10000) больше не работает, когда я запускаю функцию матричного умножения.

+1

Пожалуйста: не объявлять два типа в одном ЬурейиХ, не скрывает типа указателя в ЬурейеМ, не используйте имена с _t, они защищены от POSIX, а также использовать 'size_t' для 'rows' и' colums'. –

+0

Нет, '_t' не зарезервирован для POSIX. На самом деле это не зарезервировано ни для чего. Хотя, его следует использовать только в именах типов. Например, 'size_t' не является POSIX. – Jocke

ответ

2

M+1 указывает на память, которая непосредственно следует M (то есть, что следует за два int и double*). Это память вы выделили для данных матрицы:

matrix M = malloc(sizeof(matrix_t) + sizeof(double) * rows * columns); 
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 

Использование M+100 или M+10000, а затем пытается заполнить матрицу приведет к undefined behaviour. Это может привести к сбою программы или программе, которая, как представляется, работает (но на самом деле нарушена) или что-то среднее между ними.

0

Вам необходимо инициализировать его, потому что в противном случае (дождаться его) это неинициализированный!

И вы не можете использовать неинициализированный указатель на что угодно, кроме как генерировать неопределенное поведение.

Инициализация его до M + 1 составляет точно справа, и очень хороший код. Любое другое значение не сможет использовать выделенную вами память для этой цели.

Моя точка зрения заключается в том, что double * в конце структуры не будет автоматически указывать на эту память, что является подразумеваемой верой в ваш вопрос, почему она должна быть инициализирована. Таким образом, он должен быть установлен на соответствующий адрес.

3

Рекомендованный метод для такого рода материалов - это нестандартная матрица, используемая совместно с offsetof. Он обеспечивает правильное выравнивание.

#include <stddef.h> 
#include <stdlib.h> 

// Matrix data type 
typedef struct s_matrix 
{ 
    int rows, columns;  // Number of rows and columns in the matrix 
    double array[];   // Matrix elements as a 1-D array 
} matrix; 

// Create a new matrix with specified number of rows and columns 
// The matrix itself is still empty, however 
matrix* new_matrix(int rows, int columns) 
{ 
    size_t size = offsetof(matrix_t, array) + sizeof(double) * rows * columns; 
    matrix* M = malloc(size); 
    M->rows = rows; 
    M->columns = columns; 
    return M; 
} 
+1

Спасибо за это, я согласен, что имеет смысл не скрывать тип указателя в typdef, как указал Йенс. Однако, я думаю, вы хотите принять offsetof (matrix, array), так как matrix_t не определен в вашем коде ... – Zni

+0

Каков правильный способ добавления данных в массив? Мои старые методы, которые я использовал с первой версией кода, больше не работают. Я просто получаю сообщение об ошибке: недопустимое использование элемента гибкого массива », что бы я ни пытался. – Zni

+0

О, эта простая вещь, похоже, работает. Тем не менее, у меня проблемы с одновременным настройкой всех значений массива. Раньше я писал 'matrix * A = new_matrix (3, 2); double amatrix [] = {3, 2, 8, 1, 9, 2}; A-> array = amatrix; 'но это больше не работает. – Zni

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