0

Let's say I have a struct called Thing. If I want to have an array of "Thing", yet it doesn't have a fixed size (dynamic), how do I go about allocating space for it? Do I initially malloc space for the array itself, and then have to realloc space every time I add an element to it? For example:

struct Thing{
    char *stuff;
    char **morestuff;
    int evenmorestuff;
};

Thing *thingarray;
thingarray = malloc(sizeof(Thing));

....

//And then allocating space for elements, which will get called an unknown amount of times
Thing j;
thingarray[count] = j;

How do I set up malloc and realloc to be able to add as many elements of type Thing to the array of "Thing"?

10
  • 1
    Thing does have a fixed size. It's size is that of a char *. Commented Sep 27, 2012 at 23:46
  • I have edited Thing struct to show more attributes for it...what size would it be then? Commented Sep 27, 2012 at 23:47
  • 1
    You can just multiply your malloc call by however many elements you need, granted you know how many you want to begin with. Commented Sep 27, 2012 at 23:47
  • 1
    The code in the answer for How to store the data generated by an event in X11 handles a dynamically growing array of structs in C — the X11 tag is incidental to the array management code. The structs there are simpler than here; but the dynamic memory allocation for the content of a single struct can be added in quite easily. Commented Sep 27, 2012 at 23:49
  • 2
    @KerrekSB, actually struct Thing has the size of struct Thing. What size is it? Its sizeof(struct Thing) of course :-) Commented Sep 27, 2012 at 23:52

4 Answers 4

3

You'll probably want to use the dynamic array strategy: keep track of how many items are in it and the current capacity, then any time it fills up, double the capacity. You get amortized linear time and the random access of an array.

Sign up to request clarification or add additional context in comments.

Comments

0

You can start with a NULL pointer (Thing *thingarray = NULL;) since there is nothing in the array.

As you add items you will need to allocate memory for each item. Using malloc for the first item and realloc for additional items would work.

Comments

0

You will need to malloc it for a certain amount of "Things"

Say: malloc(sizeof(thing)*8) to get space for eight of them.

If you need more space, you will have to reallocate space using a temp variable.

4 Comments

No, you won't actually have to reallocate space using a temp variable. The standard realloc function will allocate the right amount of space, copy the old values if necessary, and then return a pointer to the new larger dynamic array (which may or may not be the same pointer as for the old dynamic array that is now garbage memory).
Huh, my apologies. I wasn't aware of realloc, I've always done it manually.
@AdamMihalcin: be careful; if you write x = realloc(x, newsize); and the realloc() fails, you've (usually) leaked memory. You need to use some variant on: void *y = realloc(x, newsize); if (y == 0) ...error handling...; else x = y;. This might be construed as using a temp variable; y has a limited duration.
@JonathanLeffler Yes, of course I'm aware that realloc, like any other standard C function that allocates memory, can fail. Saying that realloc returns a pointer to the new larger dynamic array is just like saying that malloc returns a pointer to a newly allocated chunk of memory - in both cases, the "this function call can fail" part of the description is elided.
-1

If you can, try using a vector for dynamic arrays. It will save you a lot of time and you don’t have to worry about allocation:

#include <vector>
using namespace std;

struct Thing
{
    char *stuff; 
    char **morestuff; 
    int evenmorestuff; 
};

int _tmain(int argc, _TCHAR* argv[])
{
    vector<Thing> vt;

    char stuff = 'a';
    char *morestuff = "abc";

    Thing t;
    t.stuff = &stuff;
    t.morestuff = &morestuff;
    t.evenmorestuff = 0;

    int count = 10;
    for (int i = 0; i <= count; ++i)
    {
        t.evenmorestuff = i;
        vt.push_back(t);
    }

    Thing j; 
    j.stuff = &stuff;
    j.morestuff = &morestuff;
    j.evenmorestuff = 0;

    vt[count] = j; 

    return 0;
}

3 Comments

Welcome to Stack Overflow. Interesting code; the question is tagged C but your code is using C++ headers and notations. You will get away with this if you mark your code as "This is how you'd do it in C++", but people might get grumpy without that notation. The _tmain() is a tad problematic too; you should probably diagnose that this will work on Windows, but not elsewhere. Do you run into problems with this code if you modify what stuff or morestuff points at? Fixing that would likely require constructors etc in the 'struct'.
-1 You might as well have posted Python or Ruby code ... those are equally relevant.
@Jonathan, thanks for your kind comment, next time I will know better.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.