Poperton
Poperton

Reputation: 2127

Acessing pointer makes its value change

I've been trying to write a little matrix framework in C. The problem is that acessing the matrix's components is modifying them somehow. You can see that the matrix a gets its elements changed in a weird way after being passed to matrix_scalar_multiply.

You can run the code at jdoodle.com/a/13t7

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


typedef struct Matrix
{
  int lines;            //number of lines
  int columns;          //number of columns
  float *numbers;       //elements of our matrix
} Matrix;

void
matrix_create (Matrix * a, const float *array, int lines, int columns)
{
  a->numbers = (float *) malloc (lines * columns);
  a->lines = lines;
  a->columns = columns;
  for (int i = 0; i < a->lines; i++)
    for (int j = 0; j < a->columns; j++)
      *(a->numbers + j + i * columns) = *(array + j + i * columns);
}

void
matrix_init (Matrix * a, int lines, int columns)
{
  a->numbers = (float *) malloc (lines * columns);
  a->lines = lines;
  a->columns = columns;
}

float *
matrix_element (Matrix * a, int line, int column)
{
  return a->numbers + column + line * a->columns;
}

int
matrix_scalar_multiply (float scalar, Matrix * a, Matrix * answer)
{
  matrix_init (answer, a->lines, a->columns);
  for (int i = 0; i < answer->lines; i++)
    for (int j = 0; j < answer->columns; j++)
      *matrix_element (answer, i, j) = *matrix_element (a, i, j) * scalar;
  return 0;
}

void
matrix_print (Matrix * a)
{
  for (int i = 0; i < a->lines; i++)
    {
      for (int j = 0; j < a->columns; j++)
    printf ("%f   ", *matrix_element (a, i, j));
      printf ("\n");
    }
  printf ("\n");
}

#include <stdio.h>

int
main ()
{
  Matrix a;
  Matrix b;
  float aa[4][3] = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9}, {10, 11, 12} };
  matrix_create (&a, aa, 4, 3);
  matrix_print (&a);

  matrix_scalar_multiply (3.0, &a, &b);
  matrix_print (&a);
  matrix_print (&b);
  return 0;
}

The output:

1.000000   2.000000   3.000000   
4.000000   5.000000   6.000000   
0.000000   0.000000   0.000000   
0.000000   0.000000   0.000000   

1.000000   2.000000   3.000000   
4.000000   5.000000   6.000000   
0.000000   0.000000   0.000000   
0.000000   0.000000   0.000000   

3.000000   6.000000   9.000000   
12.000000   15.000000   18.000000   
0.000000   0.000000   0.000000   
0.000000   0.000000   0.000000  

I've tried many things but couldn't find why some elements of matrix a are getting changed. If I comment matrix_init (answer, a->lines, a->columns); everything goes fine. However, you can see that I don't even pass a as argument in matrix_init.

Upvotes: 1

Views: 49

Answers (1)

Schwern
Schwern

Reputation: 164699

The problem is here.

a->numbers = (float *) malloc (lines * columns);

malloc allocates bytes, so this allocates lines * columns bytes. But a->numbers is an array of floats which are typically 4 bytes each. You've allocated only 25% of the necessary memory. When allocating memory for an array, you must also include the size of the elements.

a->numbers = malloc (lines * columns * sizeof(float));

(Side note: it's unnecessary to cast the result of malloc)

You can buy yourself a little more protection by using the size of *a->numbers instead. Then if the type of a->numbers changes, like to a double *, the allocation will still be correct.

a->numbers = malloc (lines * columns * sizeof(*a->numbers));

Upvotes: 1

Related Questions