Elena
Elena

Reputation: 77

How to pass a pointer to array of structures into a function

pointers always get me in C programing.

I am having trouble, I want to pass a pointer to an array of structs into a function so it can modify the structs and then pass the members of the array can be used in other functions later. The problem is when I think I index the array and point it to the modified struct then I try to look at the members later they aren't the modified values. Here is some of my code

typedef struct
{
  int rows;
  int columns;
  int *data;
} Mat;

int main(void)
{
  Mat result, decoded_result;
  int result_data[8] =
  { 0, 0, 0, 0, 0, 0, 0, 0 };
  int decoded_data[4] =
  { 0, 0, 0, 0 };
  result.columns = 1;
  result.rows = 8;
  result.data = &result_data[0];
  decoded_result.columns = 1;
  decoded_result.rows = 4;
  decoded_result.data = &decoded_data[0];

  Mat m1, m2, m3, m4, m5;
  m1.rows = m2.rows = m3.rows = m4.rows = m5.rows = 4;
  m1.columns = m2.columns = m3.columns = m4.columns = m5.columns = 1;

  int md1[4], md2[4], md3[4], md4[4], md5[4];

  m1.data = &md1[0], m2.data = &md2[0], m3.data = &md3[0], m4.data = &md4[0], m5.data =
      &md5[0];

  Mat mat_array[10] =
  { m1, m2, m3, m4, m5 };

  decode_data(&result, &decoded_result, mat_array);
  return 0;
}

int decode_data(Mat *result, Mat *decoded_result, Mat *mat_array)
{
  int ii;
  int size_of_EEPROM = 5;
  //steps to decode data
  for (ii = 0; ii < size_of_EEPROM; ii++)
  {
    decode(result, decoded_result); //decodes hamming 8,4, works
    mat_array[ii] = *decoded_result; ///This is where the problem is
  }
  return 0;
}

Thanks in advance for the help with pointers :)

Upvotes: 0

Views: 195

Answers (2)

alk
alk

Reputation: 70931

As Mat carries a pointer, simply assigning Mat a to Mat b won't work. At least not for the data referenced by Mat's member data.

What's needed to be done here is also called a Deep Copy. Deep coping would also create a copy of what is referenced by data.

Below is an example of how this could be done for Mat.

Note: As negative rows and columns are of no use you'd better declare Mat like this:

typedef struct
{
  size_t rows;
  size_t columns;
  int * data;
} Mat;

(As size_t is defined to be unsigned this kind of declaration makes it unnecessary to test for negative values carried by the members rows and columns before allocating the new data when deep-coping as shown below)

#include <stdlib.h> /* for malloc(), size_t */
#include <string.h> /* for memcpy() */
#include <errno.h> /* for errno, ENOMEM, EINVAL */

...

/* Deep-copies src to dst. */
/* Returns 0 on success or -1 on error. Sets errno in the latter case. */
int mat_copy(Mat * dst, const Mat * src)
{
  if ((!dst) || (!src))
  {
    errno = EINVAL;
    return -1;
  }

  dst->rows = src->row;
  dst->columns = src->columns
  dst->data = NULL;

  if (src->data)
  {
    size_t size = dst->rows * dst->columns * sizeof (*(dst->data));

    dst->data = malloc(size);
    if (!dst->data)
    {
      errno = ENOMEM;
      return -1;
    }

    memcpy(dst->data, src->data, size);
  }

  return 0;
}

Upvotes: 3

Kamen Stoykov
Kamen Stoykov

Reputation: 1881

There is rule of three in C++ when using pointers. It says that if you need one of following then you need other two always. These three are Destructor/Copy Constructor/Assign Operator.

So what happen's in your scenario. When you write mat_array[ii] = *decoded_result it actually makes:

mat_array[ii].rows = decoded_result.rows;
mat_array[ii].columns = decoded_result.columns;
mat_array[ii].data = decoded_result.data // here just assign pointers, not the entire data.

In this case you have to make assignment operator to make actual copy of data.

Upvotes: -1

Related Questions