1

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!

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
hora
  • 3,661
  • 5
  • 25
  • 26
  • Did you actually write this or did you copy it from somewhere? Try writing code, the best way to learn. You're not ready for this yet. – Hans Passant Jan 29 '10 at 02:40
  • I did sort of write it myself. I'm learning from a book (The C Programming Language by Kernighan and Ritchie), and I understand their examples of similar type stuff, except their examples are a bit simpler (less pointers). – hora Jan 29 '10 at 02:45
  • 2
    Ahhhh...that's a damn good way to learn...enjoy the book, don't get frustrated if it does not click or that you don't understand...take your time and just enjoy it! – t0mm13b Jan 29 '10 at 02:49
  • @tommieb75: I'm loving the book so far, although I think we've been forced into a pretty touch assignment to start off with so I'm experiencing a steep learning curve. I definitely need more practice. – hora Jan 29 '10 at 02:51
  • check out my answer on another thread and book mark it for yourself to come back to...http://stackoverflow.com/questions/2124935/c-strings-confusion/2125429#2125429 – t0mm13b Jan 29 '10 at 02:57

3 Answers3

4

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
  • 222,467
  • 53
  • 283
  • 367
  • 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 Jan 29 '10 at 02:48
  • 1
    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 Jan 29 '10 at 02:59
  • 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 Jan 29 '10 at 03:10
  • @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 Jan 29 '10 at 03:20
3

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
  • 233,326
  • 40
  • 323
  • 462
  • 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 Jan 29 '10 at 02:50
  • 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 Jan 29 '10 at 02:58
  • 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 Jan 29 '10 at 03:13
  • 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 Jan 29 '10 at 03:29
  • I notice you didn't say `Listnode *`, so does that allocate an array that can store Listnodes? – hora Jan 29 '10 at 03:43
  • Yes, that's exactly it. If you need to get a pointer to such a `Listnode` (say, for assigning to a `Listnode *` / `Node` variable), you would use `&nodepool[5]` (a pointer to the `Listnode` called `nodepool[5]`, which is the sixth `Listnode` in the `nodepool` array). – caf Jan 29 '10 at 03:54
0

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
  • 19,673
  • 4
  • 43
  • 72