0

I was browsing SO and found some code that raised a question for me.

struct node* BuildOneTwoThree() {
struct node *list = malloc(3 * sizeof(struct node));

list[0].data = 1;
list[0].next = list+1;
list[1].data = 2;
list[1].next = list+2;
list[2].data = 3;
list[2].next = NULL;

return list;}

I'm trying to understand how this call to malloc works and what it returns. Did it return an array of pointers? How does that work out, I didn't expect malloc to work in this way?

This seems to guarantee that the memory indices of the individual structs are one after another which I imagine could be a powerful or useful tool.

Also after such a call to malloc would it be okay to initialise the array indices as

list[0] = (struct node) {1, list +1};

Note: struct node is defined as,

  struct node{
  int data;
  struct node *next;};
M.A.A
  • 79
  • 1
  • 4
  • 1
    It returns a pointer to `3 * sizeof(struct node)` bytes of allocated memory. – tkausl Feb 05 '19 at 04:22
  • Why is it that I can index those pointers using array indices? – M.A.A Feb 05 '19 at 04:24
  • 1
    Because `list[i]` is equivalent to `*(list+i)`. – tkausl Feb 05 '19 at 04:25
  • The space returned by `malloc()` in the first call is big enough to hold an array of 3 `struct node`, and the memory pointed at is sufficiently well aligned that it is safe to cast it to a `struct node *` and use it as an array of 3 `struct node` values. The C standard requires that guarantee of 'sufficiently well aligned'. – Jonathan Leffler Feb 05 '19 at 06:21

2 Answers2

1

malloc returns a pointer to a memory region with the specified size.

The argument 3 * sizeof(struct node) says the region size is able to store 3 node structures.

Pointers and indices in arrays are interchangeable, as discussed in this answer.

João Neto
  • 1,732
  • 17
  • 28
1
struct node *list = malloc(3 * sizeof(struct node));

==> created a memory of three node structure size and list is pointed to the beginning of the memory storage. It means list=&list[0] or *list = list[0], list+1=&(list[1]) or *(list+1)=list[1], list+2=&(list[2]) or *(list+2)=list[2]

list[0] = (struct node) {1, list +1};

==> Yes, you can do that way. Here is my modification as that way, it worked fine:

struct node* BuildOneTwoThree() {
    struct node *list = (struct node *)malloc(3 * sizeof(struct node));

    list[0] = { 1, list + 1 };
    list[1] = { 2, list + 2 };
    list[2] = { 3, NULL };
    return list;
}
Loc Tran
  • 1,170
  • 7
  • 15