0

I am trying to create a dynamic array of dynamic structs but I can't get it working properly. It prints all the info but it gives return error. If I comment the line containing:

printf(" m[%i][%i] ID: %i VALUE: %f\n", i, j, m[i]->id, m[i]->values[j]);

It compiles OK and returns 0. What am I doing wrong? I am just beginning learing C and in the process of dealing with pointers.

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

typedef struct listDef{
   int id;
   float *values;
} ListSt;


int main()
{
    int max_fil, fil, col;
    max_fil = 4; /* Max 'ListSt' elements*/
    fil=2; /* Rows  */
    col=4; /* Columns */
    ListSt **m = NULL;
    int count = 0;
    int sizes[] = {4,6,8,10}; /* The sizes of each 4 elements to be created */
    m = (ListSt **)malloc(sizeof(int*)*max_fil); /* Assign a memory address for accesing 'm' (ListSt) */
    for(int i=0;i<fil;i++){
        m[i]->values = (float *)malloc(sizeof(float)*sizes[i]);
        m[i]->id = i;
        printf("-----------\n");
        printf("Element n.%i :\n\n", i);
        for(int j=0;j<sizes[i];j++){
            m[i]->values[j] = 0.1234*(i+1);
            /* If I comment the next line, it compiles OK. */
            printf(" m[%i][%i] ID: %i VALUE: %f\n", i, j, m[i]->id, m[i]->values[j]);

            int testint;
            float testfloat;
            testint = m[i]->id;
            testfloat = m[i]->values[j];
        }
    }

    free(m);
    return 0;
}
Barmar
  • 741,623
  • 53
  • 500
  • 612
Ruben Medrano
  • 161
  • 2
  • 10

4 Answers4

1
  1. m should be of type "pointer to ListSt", not "pointer to pointer to ListSt".

  2. You are allocating memory for an array of pointers:

    m = (ListSt **)malloc(sizeof(int*)*max_fil);

    ... but the elements the array remain uninitialized.

    And by the way, that should be

    sizeof (ListSt *) * (sizeof (sizes) / sizeof (* sizes))
    ^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    size of an element number of elements in array "sizes"

  3. You then go on and use the value of m[0], but you have never assigned a value to m[0]. This is called undefined behavior; at this point the program is free to do whatever it pleases, for example crashing with segmentation fault.

    More specifically, you say m[i]->values =, but m[i] is an uninitialized variable, so m[i]-> dereferences an uninitialized pointer.

AlexP
  • 4,370
  • 15
  • 15
  • " You then go on and use the value of m[0, but *you have never assigned a value to m[0]" How can I assing values to the m[0] struct then? I would like to assing it by: m[0]->id = 1; m[0]->values[0] = 0.1 m[0]->values[1] = 0.1 ...etc – Ruben Medrano Jun 14 '18 at 21:35
  • Don't just explain what he did wrong, show how to correct it. – Barmar Jun 14 '18 at 21:47
  • Yes, it would be great if someone could explain how to make it work :). I'm blocked with this, I am just beginning learning C and I need to know how to do this...it's been many days with from trial to error and reading and running many examples but with no luck tryining to find that... – Ruben Medrano Jun 14 '18 at 22:13
0

OK. I think I have it. If someone, please, could maybe check it, it would be great to have some comments about the possible errors or future problems, or just some improvements.

Here's the (modified) working code:

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

typedef struct listDef{
   int id;
   float *values;
} ListSt;


int main()
{
    int max_fil, fil, col;
    max_fil = 4; /* Max 'ListSt' elements*/
    fil=4; /* Elements  */
    ListSt *m = NULL;
    int count = 0;
    int sizes[] = {4,6,8,10,12,13}; /* The sizes of each 4 elements to be created */
    m = (ListSt *)malloc(sizeof (ListSt) * fil); /* Assign a memory address for accesing 'm' (ListSt) */

    for(int i=0;i<fil;i++){
        m[i].values = (float *)malloc(sizeof(float)*sizes[i]);
        printf("-----------\n");
        printf("Element n.%i :\n\n", i);
        for(int j=0;j<sizes[i];j++){
            m[i].id = i;
            m[i].values[j] = 0.0001*(i+1)*(j+1);
            printf(" m[%i][%i] id: [%i] val: %f\n", i, j, m[i].id, m[i].values[j]);
        }
    }

    free(m);
    return 0;
}

And it prints:

-----------
Element n.0 :

 m[0][0] id: [0] val: 0.000100
 m[0][1] id: [0] val: 0.000200
 m[0][2] id: [0] val: 0.000300
 m[0][3] id: [0] val: 0.000400
-----------
Element n.1 :

 m[1][0] id: [1] val: 0.000200
 m[1][1] id: [1] val: 0.000400
 m[1][2] id: [1] val: 0.000600
 m[1][3] id: [1] val: 0.000800
 m[1][4] id: [1] val: 0.001000
 m[1][5] id: [1] val: 0.001200
-----------
Element n.2 :

 m[2][0] id: [2] val: 0.000300
 m[2][1] id: [2] val: 0.000600
 m[2][2] id: [2] val: 0.000900
 m[2][3] id: [2] val: 0.001200
 m[2][4] id: [2] val: 0.001500
 m[2][5] id: [2] val: 0.001800
 m[2][6] id: [2] val: 0.002100
 m[2][7] id: [2] val: 0.002400
-----------
Element n.3 :

 m[3][0] id: [3] val: 0.000400
 m[3][1] id: [3] val: 0.000800
 m[3][2] id: [3] val: 0.001200
 m[3][3] id: [3] val: 0.001600
 m[3][4] id: [3] val: 0.002000
 m[3][5] id: [3] val: 0.002400
 m[3][6] id: [3] val: 0.002800
 m[3][7] id: [3] val: 0.003200
 m[3][8] id: [3] val: 0.003600
 m[3][9] id: [3] val: 0.004000

Process returned 0 (0x0)   execution time : 0.106 s
Press any key to continue.
Ruben Medrano
  • 161
  • 2
  • 10
  • This is much better. You should take the assigment to `m[i].id` outside of the the `for(j)` loop; hint: there is no `j` in `m[i].id = i`, so why should it go into a loop indexed by `j`? Also, if the exercise is to free all allocated memory, you should also free `m[i].values`; and in real life you would of course have to store somewhere the number of elements in each `m[i].values`. – AlexP Jun 15 '18 at 00:33
  • Yes Alex, you are right. But in this case `m.id` acts as an identifier number of the LisSt object. Do you think you could help me with the example I've post down? I am trying to init the list from a function, but it overwrites the values...Thanks AlexP! – Ruben Medrano Jun 15 '18 at 13:50
0

I have changed the line:

return *m;

with:

return m[i];

And it works as expected!

Ruben Medrano
  • 161
  • 2
  • 10
0

The final working code, for if it can help someone:

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

int max_fil, count;
typedef struct listDef{
   float *values;
   int id;
   int nElements;

} ListSt;



ListSt ListSt_init(ListSt *m, int i, int s){
    m[i].values = (float *)malloc(sizeof(float)*s);
    printf("-----------\n");
    printf("CREATE Element n.%i :\n\n", i);
    for(int j=0;j<s;j++){
        m[i].id = i;
        m[i].nElements = s;
        m[i].values[j] = 0.0000 + count*(0.1);
        printf("m[%i][%i]  ID: %i  TotalElements: %i  Value[%i]: %f\n", i, j, m[i].id, m[i].nElements, j, m[i].values[j]);
        count++;
    }

    return m[i];
}


int main()
{
    max_fil = 100; /* Max 'ListSt' elements addresses to be created */
    count = 0; /* Just a global counter for each 'values' */
    int sizes[] = {4,8,4}; /* The sizes of each 4 elements to be created */
    ListSt *m = NULL;
    m = (ListSt *)malloc(sizeof (ListSt) * max_fil); /* Assign a memory address for accesing 'm' (ListSt) */

    /* Lets create three lists */
    m[0] = ListSt_init(m, 0, sizes[0]);
    m[1] = ListSt_init(m, 1, sizes[1]);
    m[2] = ListSt_init(m, 2, sizes[2]);

    printf("\n-----------\n");
    printf("PRINT RESULT :\n");
    printf("-----------\n\n");
    /* Now we show the elements.... */
    for(int i=0;i<3;i++){
        printf("RESULT Element n.%i :\n\n", i);
        for(int j=0;j<sizes[i];j++){
            printf("m[%i][%i]  ID: %i  TotalElements: %i  Value[%i]: %f\n", i, j, m[i].id, m[i].nElements, j, m[i].values[j]);
        }
    }
    free(m);
    return 0;
}
Ruben Medrano
  • 161
  • 2
  • 10