Reputation: 15100
I understand how to create a struct that can be used to access an array, for example:
#include <stdio.h>
typedef struct {
int i;
int j;
int k;
} MyStruct;
int main()
{
MyStruct *ms;
int array[9];
int i;
for(i=0;i<9;++i) array[i] = i;
ms = (MyStruct *)array;
for(i=0;i<3;++i) printf("%d %d %d %d\n",i,ms[i].i,ms[i].j,ms[i].k);
return 0;
}
which allows me to access array[0] as ms[1].i and array[1] as ms[1].j etc.. However, how could I do the same thing if I wanted to use an array in the struct that is known at runtime but not at compile time? Something like:
#include <stdio.h>
typedef struct {
int *myArgs;
} MyStruct;
int main()
{
MyStruct *ms;
int array[9];
int i;
for(i=0;i<9;++i) array[i] = i;
ms = (MyStruct *)array;
for(i=0;i<3;++i) printf("%d %d %d %d\n",i,ms[i].myArgs[0],ms[i].myArgs[1],ms[i].myArgs[2]);
return 0;
}
which in that example, I would know at runtime that myArgs is length 3. But it's also possible myArgs is length 9, in which case ms should be length 1.
Edit:
I'm storing a solution set for a PDE solver that has a number of fixed-at-compile-time knowns and then an unknown number of extras. For example, my array will have X, Y, Z but then it might have 3 or 5 or 10 more things after that. So, I wanted to provide a structure that gives access to the fields for easy readability later, for example solution.x, solution.y, solution.z, solution.chemicalSpecies[0], solution.chemicalSpecies[1], etc.. The number of species is entirely unknown at compile time.
I'm using an outside library that stores the number of unknowns as an array, and I can get the array back in the form [k][j][i][numUnknowns] and it would be nice to give access like solution[k][j][i].something.
Upvotes: 2
Views: 209
Reputation: 13413
No.
In your first case, the size of your structure is the size of 3 int
variables. When you cast the pointer of your array to the pointer of your structure, each 3 int
elements will match with the one MyStruct
element, what does the magic in your code (that is theoretically non-portable).
In your second case, the size of the structure is the size of 1 pointer to int
. You must be aware that pointers have some similarities with arrays regarding usage, but they are not the same thing. Pointers are just one variable with a single value that points to a memory address. The contents of that address can then be used as an array.
In C, structs and arrays sizes are dealt at compile time, so a struct's size cannot change at runtime, thus it will do no good to your purpuse to have a pointer inside your struct, since pointer sizes are also fixed.
Maybe a good solution to you would be to use an abstract data type, like:
typedef struct {
int m; /* number of lines */
int n; /* number of columns */
int *data; /* pointer to the actual data */
} Matrix;
Then you could create ancillary functions for using the struct:
void matrix_new(Matrix *m, int rows, int columns);
int matrix_get(Matrix *m, int i, int j);
void matrix_set(Matrix *m, int i, int j, int value);
void matrix_free(Matix *m);
If that is too clumsy, you could even use a mixed approach (not too "abstract" type):
int matrix_get(Matrix *m, int i, int j)
{
return m->data[i * m->n + j];
}
int main()
{
Matrix m;
int array[9];
int i;
for(i=0;i<9;++i) array[i] = i;
m.m = m.n = 3;
m.data = array;
for(i=0;i<3;++i)
printf("%d %d %d %d\n", i,
matrix_get(&m, i, 0),
matrix_get(&m, i, 1),
matrix_get(&m, i, 2));
return 0;
}
Upvotes: 1
Reputation: 13994
Given your clarification, I would go about the problem as follows. I'd have a struct that had both the fixed x, y, and z, and then a pointer to an array, which you could set to the location of the appropriate point in the solution array. Something like this:
struct MyStruct {
int x, y, z;
int *extras;
};
...
int solutions[9];
struct MyStruct ms;
ms.x = solutions[0];
ms.y = solutions[1];
ms.z = solutions[2];
ms.extras = (solutions + 3);
...
That way, you could easily access the fields you need, and extras like:
ms.extras[0]
At least that should work, off the top of my head.
I'd also throw in a num_extras into the struct if I were you, just so you don't run off the end of the array.
Edit: If you were looking to have them be mirrored, you could instead do:
struct MyStruct {
int *x, *y, *z;
int *extras;
};
And then have:
...
int solutions[9];
struct MyStruct ms;
ms.x = &solutions[0];
ms.y = &solutions[1];
ms.z = &solutions[2];
ms.extras = (solutions + 3);
...
But that's a lot like what you had before, isn't it?
Upvotes: 0
Reputation: 35520
Trivially, given array size N
and myArgs < N
, you will have N/myArgs
complete sets of data, with a remainder of N%myArgs
items. You could base your array indexing on that fact.
However, this code looks like a maintenence nightmare. What are you trying to accomplish? There is probably a better way.
Upvotes: 1