views:

126

answers:

5

I'm trying to create an array of structs and also a pointer to that array. I don't know how large the array is going to be, so it should be dynamic. My struct would look something like this:

typedef struct _stats_t
{
 int hours[24]; int numPostsInHour;
 int days[7]; int numPostsInDay;
 int weeks[20]; int numPostsInWeek;
 int totNumLinesInPosts;
 int numPostsAnalyzed;

} stats_t;

... and I need to have multiple of these structs for each file (unknown amount) that I will analyze. I'm not sure how to do this. I don't like the following approach because of the limit of the size of the array:

# define MAX 10
typedef struct _stats_t
{
 int hours[24]; int numPostsInHour;
 int days[7]; int numPostsInDay;
 int weeks[20]; int numPostsInWeek;
 int totNumLinesInPosts;
 int numPostsAnalyzed;

} stats_t[MAX];

So how would I create this array? Also, would a pointer to this array would look something this?

stats_t stats[];
stats_t *statsPtr = &stats[0];

Thanks, Hristo

A: 

Use malloc():

http://en.wikipedia.org/wiki/Malloc

Roland Soós
+1  A: 

The second option of a pointer is good.

If you want to allocate things dynamically, then try:

stats_t* theStatsPointer = (stats_t*) malloc( MAX * sizeof(stats_t) );

as Roland suggests.

Just don't forget to

free(theStatsPointer);

when you're done.

Peter K.
the problem is i don't know MAX right away... I don't know how many files I'll have to deal with so setting a MAX would be a bad idea.
Hristo
I don't want to repeat myself, but since your code is almost identical to sblom's (other than the correct declaration of `theStatsPointer`), see point b) in my comment there. But +1 for reminding us to `free()`.
Chris Lutz
@Chris: I didn't see sblorn's until after I posted. At the time I posted, I only saw Roland's post.
Peter K.
@Hristo: MAX does not have to be a constant. If you really must, you can always use realloc() if you exceed the already existing block of memory (of size MAX stats_t structs). D'oh! Just saw Chris Lutz's comment mentioning it too.... sorry for the dupe, Chris! ;-)
Peter K.
A: 

malloc is your friend here.

stats_t stats[] = (stats_t*)malloc(N * sizeof(stats_t));

stats sort of is a pointer to the array. Or you can use stats[3] syntax as if it were declared explicitly as an array.

sblom
the problem is i don't know 'n' right away... I don't know how many files I'll have to deal with.
Hristo
a) You can't declare something like `stats_t stats[]`. That's an array with no size, not a pointer. You need `stats_t *stats`. b) I highly recommend against casting the return value of `malloc()` in C code, and the use of `sizeof(stats_t)`, both of which make changing the type of `stats` more complicated. The cast also has other, less justified stigmas associated with it.
Chris Lutz
What would you recommend instead of `sizeof`?
sblom
@sblom - `sizeof`. :P I prefer the use of `sizeof *ptr` over `sizeof(type)` because if the type of `ptr` changes, `sizeof *ptr` adjusts automatically to the correct size, while `sizeof(type)` must be manually changed and is therefore more error prone. In this case, it doesn't matter because I doubt the type of `stats` will change, but in other cases it can be helpful.
Chris Lutz
+2  A: 

This is how it is usually done:

int n = <number of elements needed>
stats_t *ptr = malloc (n * sizeof (stats_t));

Then, to fill it in,

for (int j = 0;  j < n;  ++j)
{
   ptr [j] .hours = whatever
   ptr [j] .days = whatever
   ...
}
wallyk
a) You should use `size_t` instead of `int`. `int` is a signed type, and we rarely want to allocate an array with -1 length. b) I would use `sizeof *ptr` instead of `sizeof(stats_t)`, but it doesn't matter here.
Chris Lutz
Thank you for your responses. I understand how to allocate the memory and access it, but the problem is that I will malloc one struct at a time. Everytime a new file comes along, I will malloc another struct for it. So I can't malloc 'n' structs and then go back and do work on it, rather I need to say "Here's the array, expand (add to it) once every time a new file comes along." Does that make sense?
Hristo
@Hristo: For that, use the `realloc()` function to resize an array allocated with `malloc()`. That's why it's called dynamic allocation.
Chris Lutz
ahh... thanks. That is what I was looking for. Now I just need to learn how it works and the syntax.
Hristo
+1  A: 

Based on your replies to other answers it looks like you need a dynamic data structure like a linked list. Take a look at the queue(3) set of facilities.

Nikolai N Fetissov
thanks for the suggestion. I'll look into it.
Hristo
The `queue(3)` functions aren't standard.
Chris Lutz
What C data structure library is standard?
Nikolai N Fetissov
The only C data structures that are "standard" (when "standard" means ISO C99) are pointer, array, struct and union.ISO C99 doesn't know anything about lists, sets, maps, trees, whatever. You have to use an external library for all these things.
Roland Illig