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"?

Andrew Backes
  • 1,884
  • 4
  • 21
  • 37
  • 1
    `Thing` *does* have a fixed size. It's size is that of a `char *`. – Kerrek SB Sep 27 '12 at 23:46
  • I have edited Thing struct to show more attributes for it...what size would it be then? – Andrew Backes Sep 27 '12 at 23:47
  • I wouldn't realloc for each item, grow the array by a constant factor each time. – Daniel Fischer Sep 27 '12 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. – squiguy Sep 27 '12 at 23:47
  • But I don't know how many elements I will be needing. It all depends on user input, so it could be 2, or it could be a billion. – Andrew Backes Sep 27 '12 at 23:48
  • 1
    The code in the answer for [How to store the data generated by an event in X11](http://stackoverflow.com/questions/12594282/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. – Jonathan Leffler Sep 27 '12 at 23:49
  • there is a semicolon missing after the struct definition. well, there used to be. – wildplasser Sep 27 '12 at 23:50
  • `Thing` still has a fixed size. It's `sizeof(Thing)`. It'll be something like three words. – Kerrek SB Sep 27 '12 at 23:52
  • 2
    @KerrekSB, actually struct Thing has the size of struct Thing. What size is it? Its sizeof(struct Thing) of course :-) – Josh Petitt Sep 27 '12 at 23:52
  • Note that in C, you do not get the 'automatic' name `Thing` for use in declaring the variable `thingarrray`. Somewhere, you must write `typedef struct Thing Thing;` to get that effect. You can write that line in C++ too (the `typedef`), but it is not necessary. – Jonathan Leffler Sep 28 '12 at 01:27

4 Answers4

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.

Kevin
  • 53,822
  • 15
  • 101
  • 132
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.

Terminal
  • 23
  • 2
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.

Jacobm001
  • 4,431
  • 4
  • 30
  • 51
  • 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). – Adam Mihalcin Sep 27 '12 at 23:56
  • Huh, my apologies. I wasn't aware of realloc, I've always done it manually. – Jacobm001 Sep 27 '12 at 23:58
  • @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. – Jonathan Leffler Sep 28 '12 at 01:30
  • @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. – Adam Mihalcin Sep 29 '12 at 02:19
-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;
}
Petr Dokoupil
  • 376
  • 4
  • 9
  • 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`'. – Jonathan Leffler Sep 28 '12 at 01:25
  • -1 You might as well have posted Python or Ruby code ... those are equally relevant. – Jim Balter Sep 28 '12 at 01:51
  • 1
    @Jonathan, thanks for your kind comment, next time I will know better. – Petr Dokoupil Mar 07 '13 at 22:01