Матрица C, распределяющая, не обнуляет все элементы? - PullRequest
3 голосов
/ 05 февраля 2012

Я пытаюсь написать небольшую матричную программу. Использование указателей удвоения не работает, поэтому я считаю, что самый простой способ - это иметь структуру, в которой в качестве матрицы есть #rows и #columns и массив 1d.

Но есть некоторая ошибка в инициации матрицы, когда я получаю: странные значения для индексов (0,0) и (0,1) вместо 0.

Что-то с этим возможно: matrix * mtrx = malloc (sizeof (matrix)); mtrx-> m = malloc (r * c * sizeof (int));

matrix.c:

#include <stdio.h>
#include <stdlib.h>
#include "Matrix.h"

matrix *alloc_matrix(int r, int c)
{
 matrix *mtrx = malloc(sizeof(matrix));
 mtrx->m = malloc(r * c * sizeof(int));
 if (mtrx == NULL || m == NULL) {
   printf("Out of memory.");
   exit(1);
 }
 mtrx->rows = r;
 mtrx->columns = c;
 return mtrx;
}

void free_matrix(matrix *mtrx)
{
 free(mtrx->m);
 free(mtrx);
}

void set(matrix *mtrx, int r, int c, int v)
{
 (mtrx->m)[r * mtrx->columns + c] = v;
}

int get(matrix *mtrx, int r, int c)
{
 return (mtrx->m)[r * mtrx->columns + c];
}

void print_matrix(matrix *mtrx)
{
 int i,j;
 printf("\n");
 for(i=0; i<mtrx->rows; i++) {
   for(j=0; j<mtrx->columns; j++) {
     printf("%i ", get(mtrx,i,j));
   }
   printf("\n");
 }
}

matrix.h:

struct matrix_ {
 int rows;
 int columns;
 int *m;
};
typedef struct matrix_ matrix;

matrix *alloc_matrix(int r, int c);
void free_matrix(matrix *mtrx);
void set(matrix *mtrx, int r, int c, int v);
int get(matrix *mtrx, int r, int c);
void print_matrix(matrix *m);

main.c:

#include <stdio.h>
#include <stdlib.h>
#include "Matrix.h"

int main(void)
{
 matrix *m = alloc_matrix(3,4);
 print_matrix(m);
 printf("\nm[0][0] = %i", get(m,0,0));
 set(m,0,0,0);
 printf("\nm[0][0] = %i", (m->m)[0]);
  printf("\nm[0][0] = %i", (m->m)[12]);

 return 0;
}

выход: все элементы, кроме (0,0) и (0,1), равны 0.

Ответы [ 6 ]

7 голосов
/ 05 февраля 2012

Функция malloc выделяет блок памяти, возвращая указатель на начало блока.Он не устанавливает все свои биты в ноль.

Выделение блока памяти и инициализация всех его битов в ноль - для этого предназначена функция calloc .

Или вы можете явно установить эти биты в ноль, используя memset

2 голосов
/ 05 февраля 2012

Объект, выделенный malloc, имеет неопределенное значение.При необходимости вы должны обнулить объект самостоятельно (например, используя функцию memset) или вызвать calloc вместо malloc.

1 голос
/ 05 февраля 2012

malloc не запускается с 0 (из-за проблем с производительностью ... это не всегда то, что вы хотите) ...

используйте взамен calloc ().

1 голос
/ 05 февраля 2012

malloc () не гарантирует обнуление памяти.Используйте calloc () для выделения памяти нулями.

1 голос
/ 05 февраля 2012

malloc не обнуляет выделенную память. Если вы хотите заполнить матрицу нулями при выделении, используйте calloc. В вашем случае замените:

mtrx->m = malloc(r * c * sizeof(int));

с

mtrx->m = calloc(r*c, sizeof(int));

Ответ на ваш следующий вопрос:

Однако, есть ли разница в эффективности между malloc + memset и calloc? или calloc просто malloc + memset?

Как правило, для «малых» распределений calloc эквивалентно malloc + memset. Для «больших» выделений (по крайней мере, нескольких страниц) ваша библиотека может сделать что-то более умное, полагаясь на некоторую поддержку ОС. Один из подходов заключается в том, чтобы ОС лениво обнуляла заполненные выделенные страницы по мере их фактического использования, а не обнуляла бы заполнение всех сразу после выделения.

0 голосов
/ 05 февраля 2012

Это правильно. Спецификация C не говорит, что массивы инициализированы ни к чему. Вы просто получаете часть памяти, которая будет иметь любые значения там, где раньше.

Вы можете легко инициализировать в sero, хотя: memset(mtrx->m, 0, sizeof(int) * r * c);

...