I am trying to design a data structure in C where I can store multiple arrays possibly in a struct, where each of the arrays are of a different size. For example:
typedef struct task_list
{
int total_tasks;
unsigned int *task_array
}task_list;
typedef struct node_list
{
int total_nodes;
task_list *array_node
}node_list;
Therefore if I have 5 nodes, then total_nodes will be 5 and I wish to have 5 subsequent arrays namely array_node[0], array_node[1] ... array_node[4]. Each of the arrays hold unsigned integers(tasks). The problem is each of these arrays hold a different number of tasks (total_tasks in struct task_list), therefore the size of each of the arrays will be different.
How do I create and allocate memory for each of these task array's? and what would be the best way to access them later?
If they are 1-D arrays, best way to allocate memory is through malloc. Again, since they are 1-D you can access them via array notation, being careful no to exceed the bounds given by total_nodes and total_tasks. Use free to free up arrays when deleting nodes. If array nodes gets bigger, use realloc to make the array bigger and keep the old pointers in place.
You need to allocate a node_list, then allocate its array_node to hold 5 task_lists, then allocate each of the task_lists' task_arrays to hold a variable number of tasks (using malloc(total_tasks) * sizeof(unsigned int))).
You should modify node_list so that it maintains an array of pointers to task_list:
typedef struct node_list
{
int total_nodes;
task_list **array_node;
}node_list;
Now, if you need 5 task lists, you allocate room for 5 pointers to task_list first.
node_list n;
n.total_nodes = 5;
n.array_node = malloc(n.total_nodes * sizeof(task_list *));
Then, you iterate through each array_node, and allocate an appropriately sized task_list.
for (i = 0; i < n.total_nodes; ++i) {
n.array_node[i] = allocate_task_list(task_list_size(i));
}
Then, to get to the ith task_list:
task_list *tl = n.array_node[i];
Related
I'm in a class right now that works with C and one of my assignments requires that I work with a struct that my professor wrote for us. It's actually two structs, with one struct basically containing an array of the first struct.
Here's what they look like:
typedef struct cityStruct
{
unsigned int zip;
char *town
} city;
typedef struct zipTownsStruct
{
int *towns;
city **zips;
city *cities
} zipTowns;
And here's my function for allocating memory for the zipTowns structure:
void getArrs(zipTowns *arrs, int size)
{
arrs->towns = malloc(sizeof(int) * size);
arrs->zips = malloc(sizeof(city **) * size);
arrs->cities = malloc(sizeof(city *) * size);
}
From what I understand, what I'm doing here is allocating space in memory for a certain number of ints, city pointers, and city structures, based on the size variable. I understand that this is basically what an array is.
I'm having trouble with understanding how I can access these arrays and manipulate items in it. Writing this gives me an error:
strcpy(arrs.cities[0]->town, "testTown\0");
You can see what I'm trying to do here. I want to access each "City" in the zipTowns struct by index and insert a value.
How can I access the items in these dynamically allocated array of structures?
Think of x->y as (*x).y.
arrs is not a structure, it's a pointer to a structure, and cities is not a pointer to a pointer to a structure, it's just a pointer to a structure.
Use arrs->cities[0].town instead of arrs.cities[0]->town.
However, you're still not allocating enough room for these structures. This should make it clearer what you're doing with the allocations, and should also give you enough room for your data:
arrs->towns = malloc(sizeof(*arrs->towns) * size);
arrs->zips = malloc(sizeof(*arrs->zips) * size);
arrs->cities = malloc(sizeof(*arrs->cities) * size);
With the second and third, you were only allocating enough room for a pointer to be stored instead of the actual data type.
With this approach, you will be able to access from arrs->cities[0] to arrs->cities[9] and you also will be able to access the members of each city by doing arrs->cities[<number>].<member>.
You also do not need to intentionally null-terminate your strings. This is already done for you. Therefore, you can replace "testTown\0" with "testTown".
I have looked around but have been unable to find a solution to what must be a well asked question.
Here is the code I have:
#include <stdlib.h>
struct my_struct {
int n;
char s[]
};
int main()
{
struct my_struct ms;
ms.s = malloc(sizeof(char*)*50);
}
and here is the error gcc gives me:
error: invalid use of flexible array member
I can get it to compile if i declare the declaration of s inside the struct to be
char* s
and this is probably a superior implementation (pointer arithmetic is faster than arrays, yes?)
but I thought in c a declaration of
char s[]
is the same as
char* s
The way you have it written now , used to be called the "struct hack", until C99 blessed it as a "flexible array member". The reason you're getting an error (probably anyway) is that it needs to be followed by a semicolon:
#include <stdlib.h>
struct my_struct {
int n;
char s[];
};
When you allocate space for this, you want to allocate the size of the struct plus the amount of space you want for the array:
struct my_struct *s = malloc(sizeof(struct my_struct) + 50);
In this case, the flexible array member is an array of char, and sizeof(char)==1, so you don't need to multiply by its size, but just like any other malloc you'd need to if it was an array of some other type:
struct dyn_array {
int size;
int data[];
};
struct dyn_array* my_array = malloc(sizeof(struct dyn_array) + 100 * sizeof(int));
Edit: This gives a different result from changing the member to a pointer. In that case, you (normally) need two separate allocations, one for the struct itself, and one for the "extra" data to be pointed to by the pointer. Using a flexible array member you can allocate all the data in a single block.
You need to decide what it is you are trying to do first.
If you want to have a struct with a pointer to an [independent] array inside, you have to declare it as
struct my_struct {
int n;
char *s;
};
In this case you can create the actual struct object in any way you please (like an automatic variable, for example)
struct my_struct ms;
and then allocate the memory for the array independently
ms.s = malloc(50 * sizeof *ms.s);
In fact, there's no general need to allocate the array memory dynamically
struct my_struct ms;
char s[50];
ms.s = s;
It all depends on what kind of lifetime you need from these objects. If your struct is automatic, then in most cases the array would also be automatic. If the struct object owns the array memory, there's simply no point in doing otherwise. If the struct itself is dynamic, then the array should also normally be dynamic.
Note that in this case you have two independent memory blocks: the struct and the array.
A completely different approach would be to use the "struct hack" idiom. In this case the array becomes an integral part of the struct. Both reside in a single block of memory. In C99 the struct would be declared as
struct my_struct {
int n;
char s[];
};
and to create an object you'd have to allocate the whole thing dynamically
struct my_struct *ms = malloc(sizeof *ms + 50 * sizeof *ms->s);
The size of memory block in this case is calculated to accommodate the struct members and the trailing array of run-time size.
Note that in this case you have no option to create such struct objects as static or automatic objects. Structs with flexible array members at the end can only be allocated dynamically in C.
Your assumption about pointer aritmetics being faster then arrays is absolutely incorrect. Arrays work through pointer arithmetics by definition, so they are basically the same. Moreover, a genuine array (not decayed to a pointer) is generally a bit faster than a pointer object. Pointer value has to be read from memory, while the array's location in memory is "known" (or "calculated") from the array object itself.
The use of an array of unspecified size is only allowed at the end of a structure, and only works in some compilers. It is a non-standard compiler extension. (Although I think I remember C++0x will be allowing this.)
The array will not be a separate allocation for from the structure though. So you need to allocate all of my_struct, not just the array part.
What I do is simply give the array a small but non-zero size. Usually 4 for character arrays and 2 for wchar_t arrays to preserve 32 bit alignment.
Then you can take the declared size of the array into account, when you do the allocating. I often don't on the theory that the slop is smaller than the granularity that the heap manager works in in any case.
Also, I think you should not be using sizeof(char*) in your allocation.
This is what I would do.
struct my_struct {
int nAllocated;
char s[4]; // waste 32 bits to guarantee alignment and room for a null-terminator
};
int main()
{
struct my_struct * pms;
int cb = sizeof(*pms) + sizeof(pms->s[0])*50;
pms = (struct my_struct*) malloc(cb);
pms->nAllocated = (cb - sizoef(*pms) + sizeof(pms->s)) / sizeof(pms->s[0]);
}
I suspect the compiler doesn't know how much space it will need to allocate for s[], should you choose to declare an automatic variable with it.
I concur with what Ben said, declare your struct
struct my_struct {
int n;
char s[1];
};
Also, to clarify his comment about storage, declaring char *s won't put the struct on the stack (since it is dynamically allocated) and allocate s in the heap, what it will do is interpret the first sizeof(char *) bytes of your array as a pointer, so you won't be operating on the data you think you are, and probably will be fatal.
It is vital to remember that although the operations on pointers and arrays may be implemented the same way, they are not the same thing.
Arrays will resolve to pointers, and here you must define s as char *s. The struct basically is a container, and must (IIRC) be fixed size, so having a dynamically sized array inside of it simply isn't possible. Since you're mallocing the memory anyway, this shouldn't make any difference in what you're after.
Basically you're saying, s will indicate a memory location. Note that you can still access this later using notation like s[0].
pointer arithmetic is faster than arrays, yes?
Not at all - they're actually the same. arrays translate to pointer arithmetics at compile-time.
char test[100];
test[40] = 12;
// translates to: (test now indicates the starting address of the array)
*(test+40) = 12;
Working code of storing array inside a structure in a c, and how to store value in the array elements Please leave comment if you have any doubts, i will clarify at my best
Structure Define:
struct process{
int process_id;
int tau;
double alpha;
int* process_time;
};
Memory Allocation for process structure:
struct process* process_mem_aloc = (struct process*) malloc(temp_number_of_process * sizeof(struct process));
Looping through multiple process and for each process updating process_time dyanamic array
int process_count = 0;
int tick_count = 0;
while(process_count < number_of_process){
//Memory allocation for each array of the process, will be containting size equal to number_of_ticks: can hold any value
(process_mem_aloc + process_count)->process_time = (int*) malloc(number_of_ticks* sizeof(int));
reading data from line by line from a file, storing into process_time array and then printing it from the stored value, next while loop is inside the process while loop
while(tick_count < number_of_ticks){
fgets(line, LINE_LENGTH, file);
*((process_mem_aloc + process_count)->process_time + tick_count) = convertToInteger(line);;
printf("tick_count : %d , number_of_ticks %d\n",tick_count,*((process_mem_aloc + process_count)->process_time + tick_count));
tick_count++;
}
tick_count = 0;
the code generated will be identical (array and ptr). Apart from the fact that the array one wont compile that is
and BTW - do it c++ and use vector
I have the following code:
typedef struct
{
int name;
int info[1];
} Data;
then I have five variables:
int a, b, c, d, e;
how can I use this as a flexible array to keep all the values of the five variables?
To do this properly, you should declare the flexible array member as an incomplete type:
typedef struct
{
int name;
int info[];
} Data;
Then allocate memory for it dynamically with
Data* data = malloc(sizeof(Data) + sizeof(int[N]));
for(int i=0; i<N; i++)
{
data->info[i] = something; // now use it just as any other array
}
EDIT
Ensure that you are using a C99 compiler for this to work, otherwise you will encounter various problems:
If you allocate an array of length 1, then you will malloc 1 item for the first element of the array together with the struct, and then append N bytes after that. Meaning you are actually allocating N+1 bytes. This is perhaps not what one intended to do, and it makes things needlessly complicated.
(To solve the above problem, GCC had a pre-C99 extension that allowed zero-length arrays, which isn't allowed in standard C.)
Pre-C99, or in any other context than as a flexible array member, C doesn't allow incomplete array types as the one shown in my code.
C99 guarantees that your program is well-defined when using a flexible array member. If you don't use C99, then the compiler might append "struct padding" bytes between the other struct members and the array at the end. Meaning that data->info[0] could point at a struct padding byte and not at the first item in your allocated array. This can cause all kinds of weird, unexpected behavior.
This is why flexible array members were called "struct hack" before C99. They weren't reliable, just a dirty hack which may or may not work.
That kind of structure is a somewhat common idiom in C; the idea is that you allocate extra space at the end of the struct, where the elements of info after the first are actually stored. The size-1 array member at the end of the struct then allows you to use array syntax to access this data.
If you want to store 5 elements you'll have to do:
Data * data=malloc(sizeof(Data)+sizeof(int)*4); /* 4 because the first element is
already included in the size of
the struct */
/* error checking omitted ... */
data->info[0]=a;
data->info[1]=b;
data->info[2]=c;
data->info[3]=d;
data->info[4]=e;
/* ... */
/* when you don't need d anymore remember to deallocate */
free(data);
You may also write a helper function to ease the allocation:
Data * AllocateData(size_t elements)
{
if(elements==0)
return NULL;
return malloc(sizeof(Data)+sizeof(int)*(elements-1));
}
and the example above would be
Data * data=AllocateData(5);
/* then as above */
This is called flexible arrays and was introduced in C99. Often called a struct hack too.
In C99, the flexible array member should be declared without a size.
You need to dynamically allocate memory that can hold more memory than the size of the struct.
As the array is the last member in the struct, you can index it past its size, provided you allocated enough memory for it.
typedef struct
{
int name;
int info[1];
} Data;
Data *d = malloc(sizeof(*d) + (5 * sizeof(int)); //enough for the struct and 5 more ints.
//we have enough room for 6 elements in the info array now
//since the struct has room for 1 element, and we allocated room for another 5 ints
d->info[0] = 1;
d->info[1] = 2;
d->info[2] = 3;
d->info[3] = 4;
d->info[4] = 5;
d->info[5] = 6;
Using an array member with 1 size int info[1]; in this manner is technically undefined behavior - but will work fine on many popular compilers. With a C99 compiler this is supported by a flexible array member declared as int info[];. Read more here
I currently have no code, because I don't know how to do this at all. Could I just, by myself, calculate how many bytes is needed for each lower-level struct and malloc it to it? That's really terrible coding, isn't it. Here's the two structs I'm trying to mash together:
struct property {
int d;
char name [111]; // I just malloc this like I would a normal array, right?
char descr [1025]; // Ditto.
}
struct category {
int d [413]; // The d's of all the child structs sorted highest to lowest.
char name [111];
struct property property [413]; // This. How do I allocate this?
}</code>
Do I have to do struct property* property = (struct property*) malloc(sizeof(struct property) * 413);? Will the malloc of the array within remain intact? How do mallocs in structs behave in general?
You don't have a pointer member inside your structure property so you don't need to malloc any of your structure members.
When you malloc for the structure it will give you enough memory to hold all the structure members including arrays, exceptions are pointer structure members(You don't have any).
Your malloc without the cast would do fine. It allocates contiguous memory for the whole array. The arrays inside the struct's are all allocated along with it, they are proper arrays and not pointers.
Sizeof will give you the size of your entire structure. It properly accounts for the size of arrays and structures.
However, 413 items seems arbitrary. Would a variable sized structure work better for you?
In that case, calculating the size ahead of time to avoid mallocs is a good performance idea. Malloc can be slow, it can require locks, and the heap can fragment over time. This example shows you how to make a "variable length" structure with a pointer instead of an array or a variable length array at the end of your structure:
struct category
{
int cItems; // need this if handling variable # of items now.
int *d; // ptr instead of array
char *name; // ptr again
struct property property[0]; // var length array
}
int cItems = 413; // or whatever
// this is a nifty trick to get the size of a variable length struct:
int cbCategory = (size_t)(&((struct category*)0)->property[cItems]);
int cbD = sizeof(int)*cItems;
int cbName = sizeof(char)*cItems;
struct category *pCategory = (struct category*)malloc(cbCategory + cbD + cbName);
// wire up d:
pCategory->d = (int*)((char*)pCategory + cbCategory);
// or wire d up this way:
pCategory->d = (int*)&pCategory->property[cItems];
// wire up name
pCategory->name = (char*)pCategory->d + cbD;
// or wire up name this way
pCategory->name = (char*)&pCategory->d[cItems];
// set items
pCategory->cItems = cItems;
Note, I assumed that d had 413 elements to it. I could have just as easily left it a an array.
If I create a struct in one class as so
typedef struct
{
int numberOfTiles;
// an array of ints here
int *tileArray;
} CollisionLayer;
is it possible to create an array of ints with an empty [] and set the size on creation? Or how would this array be created? dynamically with a pointer? I will know the size of the array when creating one of these struct "objects", if it is possible to fill in the size of the array on creation, how is the array declared in the struct above?
You will need to initialize the array yourself:
CollisionLayer layer;
layer.numberOfTiles = numberOfTiles;
layer.tileArray = (int*)malloc(sizeof(int) * numberOfTiles);
Or, if you want to create the struct on the heap:
CollisionLayer* pl = (CollisionLayer*)malloc(sizeof(CollisionLayer));
pl->numberOfTiles = numberOfTiles;
pl->tileArray = (int*)malloc(sizeof(int) * numberOfTiles);
// When you are done:
free(pl->tileArray);
free(pl);
The other option would be to hardcode a fixed size limit into CollisionLayer, e.g.:
typedef struct
{
int numberOfTiles;
// an array of ints here
int tileArray[100];
} CollisionLayer;
Of course this will be less desirable in all respects, but it's your only option if you don't want to manage memory manually.
If you don't know the size at compile time, then you must allocate the memory using malloc() at runtime. To use an actual array in C, you must know the size when the code is compiled.
tileArray is a pointer to int. malloc/calloc should be used to create the object to which it will point to. This should happen when creating an object of CollisionLayer.
Defining a struct in which the array [] is empty is not a good idea, refer this. It speaks of C++, bit it should apply for C as well.
VLAs cannot be members of structs so you will need to allocate the memory with malloc when you create the struct object.