Ruben Medrano
Ruben Medrano

Reputation: 159

C dynamic array of dynamic struct

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;
}

Upvotes: 0

Views: 150

Answers (4)

Ruben Medrano
Ruben Medrano

Reputation: 159

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;
}

Upvotes: 0

Ruben Medrano
Ruben Medrano

Reputation: 159

I have changed the line:

return *m;

with:

return m[i];

And it works as expected!

Upvotes: 0

Ruben Medrano
Ruben Medrano

Reputation: 159

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.

Upvotes: 0

AlexP
AlexP

Reputation: 4430

  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.

Upvotes: 1

Related Questions