How I do use dynamic arrays inside nested structs? - c

I have the following struct
#define MAXCHAR 80
#define MAXARRAY 200
#define MAXCELLS 15
struct structInfoNet
{
int idCell;
char MacAddress[MAXCHAR];
char Essid[MAXCHAR];
char Mode[MAXCHAR];
int Channel;
};
typedef struct structInfoNet Net;
struct structCell
{
int nPAS;
Net Red[MAXARRAY]; // How I do Convert this to a Dynamic Array ?
};
typedef struct structCell Cell;
int main()
{
int numCelda;
Cell cell[MAXCELLS]; // I do not care structure Cells being a fixed array
// But I want the nested structure inside Cells (Net) being a dynamic array
}
I would like to use dynamic arrays, and convert the nested structure Net on a dynamic array that I can manage using malloc (and realloc to change the size), but I do not understand how to do it. Be aware that I do not need to change the main estructure (the outter structure Cell, that can remain as a normal array). Is there a way to do such a thing ?
Thks!

Related

How to expose variable sized arrays inside C struct in swig?

I'm struggling for a few days now to find a solution to wrap a C struct containing multiple variable-sized int arrays (stored as pointers) in swig.
Suppose the following minimal example:
typedef struct {
size_t length;
int *a;
int *b;
} mystruct;
where both a and b are pointers to int arrays allocated somewhere in C. The size of both arrays is stored in the length member.
Now, what I would really like to have is two-fold:
access to a and b members in objects of type mystruct should be safe, i.e. exceptions should be thrown if index is out-of-bounds.
the data in a and b must not be copied-over into a python list or tuple but I want to provide __getitem__ methods instead. The reason for that is that the actual struct consists of many such arrays and they get really huge and I don't want to waste any memory by duplicating them.
I've seen examples how to accomplish this with fixed-sized arrays by writing wrapper classes and templates for each member that internally store the size/length of each array individually, e.g.: SWIG interfacing C library to Python (Creating 'iterable' Python data type from C 'sequence' struct) and SWIG/python array inside structure.
However, I assume once I would wrap a and b into a class to enable them to be extended with __getitem__ methods, I won't have access to the length member of mystruct, i.e. the 'container' of a and b.
One thing I tried without success was to write explicit _get and _set methods
typedef struct {
size_t length;
} mystruct;
%extend mystruct {
int *a;
};
%{
int *mystruct_a_get(mystruct *s) {
return mx->a;
}
int *mystruct_b_get(mystruct *s) {
return mx->b;
}
...
%}
But here, the entire arrays a and b would be returned without any control of the maximum index...
My target languages are Python and Perl 5, so I guess one could start writing complicated typemaps for each language. I've done that before for other wrappers and hope there is a more generic solution to my situation that involves only C++ wrapper classes and such.
Any help or idea is appreciated!
Edit for possible solution
So, I couldn't let it go and came up with the following (simplified) solution that more or less combines the solutions I already saw elsewhere. The idea was to redundantly store the array lengths for each of the wrapped arrays:
%{
/* wrapper for variable sized arrays */
typedef struct {
size_t length;
int *data;
} var_array_int;
/* convenience constructor for variable sized array wrapper */
var_array_int *
var_array_int_new(size_t length,
int *data)
{
var_array_int *a = (var_array_int *)malloc(sizeof(var_array_int));
a->length = length;
a->data = data;
return a;
}
/* actual structure I want to wrap */
typedef struct {
size_t length;
int *a;
int *b;
} mystruct;
%}
/* hide all struct members in scripting language */
typedef struct {} var_array_int;
typedef struct {} mystruct;
/* extend variable sized arrays with __len__ and __getitem__ */
%extend var_array_int {
size_t __len__() const {
return $self->length;
}
const int __getitem__(int i) const throw(std::out_of_range) {
if ((i < 0) ||
(i >= $self->length))
throw std::out_of_range("Index out of bounds");
return $self->data[i];
}
};
/* add read-only variable sized array members to container struct */
%extend mystruct {
var_array_int *const a;
var_array_int *const b;
};
/* implement explict _get() methods for the variable sized array members */
%{
var_array_int *
mystruct_a_get(mystruct *s)
{
return var_array_int_new(s->length, s->a);
}
var_array_int *
mystruct_b_get(mystruct *s)
{
return var_array_int_new(s->length, s->b);
}
%}
The above solution only provides read access to the variable sized arrays and does not include any NULL checks for the wrapped int * pointers. My actual solution of course does that and also makes use of templates to wrap variable sized arrays of different types. But I refrained from showing that here for the sake of clarity.
I wonder if there is an easier way to do the above. Also the solution only seems to work in Python so far. Implementing something similar for Perl 5 already gives me a headache.

How to set size of nested structure?

I'd like to make a simple database without making a dynamic sized array. I thought nested structure can help me, but so far it's nothing but pain. This was my idea when I started:
#include <stdio.h>
#define MAXDOG 50
#define MAXCHAR 20
struct allDog {
int size;
struct oneDog[MAXDOG] {
char dogName[MAXCHAR];
char OwnerName[MAXCHAR];
};
};
I'm pretty sure that my problem is the [MAXDOG] part after struct oneDog, can I give a static size somehow to the inner structure?
You can read the part of the exam I try to do below:
The program asks for the Dog's & Owner's name (MAX 50) then prints out the data. You can't use dynamic arrays...
You're overcomplicating things - try this:
#define MAXDOG 50
#define MAXCHAR 20
typedef struct { // struct which defines one dog
char dogName[MAXCHAR];
char ownerName[MAXCHAR];
} Dog;
typedef struct { // struct which contains array of dogs
int size; // no of dogs in array currently
Dog dogs[MAXDOGS]; // array of up to MAXDOGS dogs
} Dogs;
You sized the type not the member, syntax is:
struct allDog { // type
int size;
struct oneDog { // type
char dogName[MAXCHAR];
char OwnerName[MAXCHAR];
} dogs[MAXDOG]; // member
};
Take care to be consistent with caps in naming, member OwnerName should be written ownerName to be consistent with other members. Types are generally typed AllDog and OneDog, to differentiate in between members and types.

Initializing size of struct array after declaration in C?

I've done some searching around, but nothing I've found has answered my question specifically regarding structs:
In my program I have two structures: one contains data, the other contains an array of the first structure (used to make returning struct arrays easier).
I do not know the size of the aforementioned structure array until running a few lines of code. From what I've found there isn't a way to define the size of an array (or any type) after it has already been declared, although I would like to know if this holds true for structs.
If not, is there way to define the size of a previously declared array within a struct without using malloc? Using malloc with struct arrays seems a bit complicated and I haven't been able to wrap my head around it.
typedef struct
{
char **data;
} struct1;
typedef struct
{
struct1 data[];
} struct2;
int main(int argc, char **argv)
{
//Pretend there is code here that finds the size I need
size = 5;
struct2 Info;
Info.data = new struct1[size]; //Clearly this won't work, but does C offer anything comparable?
return 0;
}

how to allocate memory to a struct that contains a dynamic array? (C)

I am not quite clear on how to allocate memory to a struct pointer that contains a dynamic array field. for example, I have the following struct:
typedef struct log_file {
char *name;
int updatesize;
int numupdates;
int *users; /* dynamic array of integers */
} log_data;
When I created a pointer of log_data using: log_data *log_ptr = malloc(sizeof(log_data));
How do I allocate enough memory for the dynamic array users in the struct?
How about:
log_ptr->users = malloc(sizeof(int)*numOfUsers);
Or if you want to keep it independent of the type of *users:
log_ptr->users = malloc(sizeof(*log_ptr->users)*numOfUsers);

2D array problem

I need to make one 2D array in which one column store the pointer of some structure & another column store one 32 bit magic number.
how can i do it in 2D array.?
or any other method to keep track of this two columns info?
You can use:
// The struct that will hold the pointer and the magic number
struct data {
void *other_struct_ptr;
unsigned int magic_number;
};
// Declare my array
struct data array[N];
Where N is the size of your array. Now just fill your data into the array. For example:
array[0].other_struct_ptr = NULL; // I used NULL for simplicity
array[0].magic_number = 0xDEADC0DE;
array[1].other_struct_ptr = NULL;
array[1].magic_number = 0xCAFEBABE;
Define a struct like this:
struct data_t
{
void *pointer;
int magic_number;
};
Then use following array:
data_t values[100]; //100 is just for example
Or maybe you need such 2D array:
data_t values[100][100]; //100s are just for example

Resources