views:

114

answers:

3

I'm writing a bit of code for a class, but since I have no experience in C I'm a bit unsure of what the code I've written actually does. Particularly what the memory looks like. Here's the relevant bits:

typedef struct listnode *Node;
typedef struct listnode {
    void *data;
    Node next;
    Node previous;
} Listnode;

typedef struct listhead *LIST;
typedef struct listhead {
    int size;
    Node first;
    Node last;
    Node current;
} Listhead;

#define HALLOCSIZE 50

static LIST hallocbuf[HALLOCSIZE];
static LIST *hallocp = hallocbuf;

LIST *CreateList()
{
    if(hallocbuf + HALLOCSIZE - hallocp >= 1)
    {
        LIST temp;
        temp->size = 0;
        temp->first = NULL;
        temp->last = NULL;
        temp->current = NULL;

        *hallocp = temp;
        return hallocp;

    }else
        return NULL;
}

So my question is, in the CreateList function, how is the program allocating memory for temp? And does the code *hallocp = temp copy the temp LIST into the hallocbuf array? I am trying to have all my LIST structs sit in the allocated memory for hallocbuf. Is this what I'm doing? I'm a bit uncertain of how the typedef, structs and pointers play together.

Thanks!

+4  A: 

So my question is, in the CreateList function, how is the program allocating memory for temp?

It isn't, which is a problem. It should do something like this:

temp = malloc(sizeof(Listhead));

And does the code *hallocp = temp copy the temp LIST into the hallocbuf array?

It copies the pointer that was saved in temp into the first element of hallocbuf (assuming that hallocp hasn't been changed anywhere and still has the value that it has been initialized to, pointing to hallocbuf[0]).

Generally it's not usually a good idea to hide the fact that LIST and Node are pointers behind typedefs. It's much clearer where memory needs to be allocated of freed if it's obvious which variables are pointer, and having an explicit * in the variable declaration makes that clear.

sth
Thanks for the help. How do I not hide the fact that List and Node are pointers? I don't really get how typedef works... I've read up on them but the examples I've seen are a lot simpler.
hora
Typedefs work like variable declarations, only that they declare a new name for a type. So a `LIST` really is a `struct listhead *`. Also `Listhead` is a typedef for `struct listhead`, so you could also write `Listhead *` instead of `LIST`. Analog to that `Node` is the same as `Listnode *` and `struct listnode *`.
sth
So then *hallocp is actually a pointer to a pointer? Given that LIST is the same as Listhead *, I'd have Listhead * *hallocp. Is that right? Thanks for helping me out!
hora
@hora: Yes, `hallocp` is a pointer to a pointer. The `hallocbuf` array is an array of pointers, and `hallocp` points to the first of these pointers in the array.
sth
+3  A: 

temp is allocated in the space used for objects with "automatic storage duration" - this is usually on a runtime stack, but you don't really need to know the details. The space is deallocated when the block in which it was allocated is exited (in your case, when you hit the return).

The line *hallocp = temp; does indeed copy the value of temp into the memory that hallocp is pointing at, which is hallocbuf[0].

The problem is that temp is just a pointer itself - and it's not pointing at anything. This is called a "dangling pointer". This means that when you try to access what it's pointing at, you have an error. That happens in these lines:

temp->size = 0;
temp->first = NULL;
temp->last = NULL;
temp->current = NULL;

You can't have your structs sit in the memory allocated for hallocbuf, because it doesn't have room for structs - it's just an array of pointers, not an array of structs.

caf
Right, I get that. So basically the actual structs would sit on the heap, and what I created is an array of pointers TO these structs. Am I correct?
hora
Well, that's how you've set it up (as long as you add in a `malloc` to actually allocate some memory for `temp` to point to, as the others have said). But there doesn't seem to be a good *reason* to do things like that - what are you really trying to achieve?
caf
What I'm trying to do is create a Linked List type, and I have to have a statically allocated array that stores my Listheads and Listnodes, and then a whole bunch of methods to manipulate the Lists.
hora
OK, that makes sense - presumably they want you to avoid `malloc` for now. In this case, your arrays will need to be declared like this: `static Listnode nodepool[MAX_NODES];` and `static Listhead headpool[MAX_LISTS];`. You'll also have to have static variables to keep track of how many `Listnode`s and `Listhead`s from the arrays you've allocated.
caf
I notice you didn't say `Listnode *`, so does that allocate an array that can store Listnodes?
hora
caf
A: 

If LIST were

typedef struct listhead LIST;

and you accessed temp

temp.size = 0;
...

then

*hallocp++ = temp;

would use hallocp as a pointer into the hallocbuf buffer and place the newly initialized element there. Not the best way to do it, though. You could replace temp with

hallocp->size = 0;
...
++hallocp;
Richard Pennington