0

I am trying to create a struct containing 2 Variable Length Array (buffer_size is the variable parameter acquired at run time). Here is my code:

struct data {
  float *c;   //2D array
  float *mtdt;  //1D array
};

struct data c_matrice;  
c_matrice.c = malloc((90 * sizeof (float*) * buffer_size)); 
c_matrice.mtdt = malloc(90 * sizeof (float*));

The idea is to link the structure's members to arrays that are dynamically allocated. Here is the compiler error

expected « = », « , », « ; », « asm » or « __attribute__ » before « . » token
 c_matrice.c = malloc((90 * sizeof (float*) * buffer_size));

And when I try to access those members, I get

subscripted value is neither array nor pointer nor vector

I haven't been able to find a solution to my problem in the previous questions. Frankly as a beginner I don't get everything. What am I missing?

EDIT 1: Ok I got rid of the first error by moving the last two lines into my main.c rather than a .h file (This was a basic stupid mistake). Now I still face the

subscripted value is neither array nor pointer nor vector

when I try to access the struct with something like this

pmoy = pow(10,(c_matrice->c[i][curve2apply]/20))*pmax;

And by the way, the whole code is really big, and what I presented you was a small part of the actual code.

Jens
  • 69,818
  • 15
  • 125
  • 179
Victor Deleau
  • 875
  • 5
  • 17
  • 2
    What exactly is the problem? The code you have shown looks okay to me so far. – Codor Apr 07 '17 at 11:30
  • You need to allocate memory for the struct too. – WhilseySoon Apr 07 '17 at 11:31
  • 1
    But the `c` member *isn't* a "2d array", it's just a pointer which you make point to a chunk of memory that is `90 * sizeof (float*) * buffer_size` bytes large. – Some programmer dude Apr 07 '17 at 11:31
  • 1
    It doesn't seem right that you want to allocate for 1D array of `float`, but use `sizeof(float*)`. It's also unclear how you are going to use those arrays. Please read on and provide [mcve]. – user694733 Apr 07 '17 at 11:33
  • WhilseySoon, how am I suppose to allocate the memory for the struct ? I feel like I already have. And I think you've got one part of the problem user694733. So how can I point the structure members to a dynamic array ? – Victor Deleau Apr 07 '17 at 11:43
  • There is a compiler error, not a runtime error. Don't look at memory allocation but at your syntax. – Eregrith Apr 07 '17 at 11:47
  • 1
    No, the posted code does not give that compiler warning. Copy/paste the actual code. – Lundin Apr 07 '17 at 11:47
  • This is really my code. Maybe because I am into a .h file ? 'struct data { float *c; float *mtdt; }; struct data c_matrice; c_matrice.c = malloc((90 * sizeof (float*) * buffer_size)); c_matrice.mtdt = malloc(90 * sizeof (float*));' – Victor Deleau Apr 07 '17 at 11:50
  • Post the actual code in the question, not a correction in the comments. – Ian Abbott Apr 07 '17 at 11:52
  • 1
    Are you trying to call `malloc` from outside a function? – Ian Abbott Apr 07 '17 at 11:56
  • Yes I did ... moving those parts back to my main.c resolved the first error. Thank you ! – Victor Deleau Apr 07 '17 at 12:03
  • the type for c must be `float **` if it's supposed to contain a 2d array. Then, the type used with `malloc` is ok (`rowNum * sizeof(float *)`) - but then, all elements in `c` need to be initialized to point to arrays of float as well (i.e., run through all values in `c` and `malloc(colNum * sizeof(float)` for each). – starturtle Apr 07 '17 at 12:06
  • @WaspCo: If you work on matrices and vectors (and especially if on submatrices or vectors of existing matrices), you might wish to take a look at [some of my suggestions here](http://stackoverflow.com/a/34862940/1475978). It shows a way you can use a single, reference-counted datatype for both matrix and vector data, with easy memory management (the examples are limited to single-threaded programs, however). – Nominal Animal Apr 07 '17 at 12:27

2 Answers2

0

If c is a member of the struct, then you must use c_matrice.c, not c_matrice->c. And carefully note everything people tell you about c not being a two dimensional array. To allocate these, there's a ton of question/answers on SO and you must not ask that question once again. :-)

Jens
  • 69,818
  • 15
  • 125
  • 179
  • In addition: `->` operator is a shortcut for `(*c_matrice).c` which is mainly used when `c_matrice` is a pointer and not the struct itself. In short : if you have `struct data *c_matrice` you use `->` to access members. In your case you use `.` – Eregrith Apr 07 '17 at 12:21
0

What you've done here:

c_matrice.c = malloc((90 * sizeof (float*) * buffer_size)); 

Is allocate one long buffer of size 90 * size of pointer-to-float * buffer_size.

You have a bunch of options in how you implement a 2D array in C. One approach is to change what you have there to:

c_matrice.c = malloc((90 * sizeof (float) * buffer_size)); 

So you've allocated space for 90*buffer_size floats (rather than pointers to floats).

You then need to calculate indexes yourself:

float get_matrix_element(struct data *c_matrix, size_t row, size_t column)  {      
    return c_matrix->c[row*buffer_size+column];
}

That's a very popular and very efficient way of storing the data because it's stored as one block of memory and you can do useful things like allocate it in a single block and iterate through it without concern for structure:

float get_matrix_sum(struct data *c_matrix)  {      
    size_t sz=buffer_size*90;
    float sum=0.0f;
    for(size_t i=0;i<sz;++i){
       sum+=c_matrix->c[i];
    }
    return sum;
}

There are other ways of doing this including:

  1. Declare a 90 long 1D array of pointers to float and then allocate rows of floats.

The downside is 91 malloc()/free() operations instead of 1. The upside is you could allocate a ragged array with different length rows.

  1. Declare a static (compile time) sized array float c[90][buffer_size];

Where buffer_size is a compile time constant. The downside is it's compile time fixed (and if large and a local variable may break the stack). The upside is managing the internal r*90+c row calculation is taken off you.

Persixty
  • 8,165
  • 2
  • 13
  • 35