schullzroll
schullzroll

Reputation: 167

Obtain data deep in structures C

I just encountered something rather weird. When I have a pointer to a structure which contains another pointer to a structure of the same type, if I want to get the data from the "second" structure (if you didn't get what I mean, maybe the diagram below will describe it better)...

                      1
          ptr ---> |------|       2
                   | next ---> |------|
                   | data |    | next |
                   |------|    | data | <= data which i desire to get 
                               |------|

How should I access the desired data if I don't really want to declare another pointer variable ?

What if the desired data is even more "deeper"?

I tried something like this for a test, but it feels a little.. "broken looking" to me and I'm really surprised by the fact that there were no compiler warnings:

ptr2struct.c

#include <stdio.h>
#include <stdlib.h>

typedef struct Structure structure;
struct Structure {
    int data;
    structure *next;
};

int main()
{
    structure *ptr = malloc(sizeof(*ptr));

    /* First structure */
    ptr->data = 1;
    ptr->next = malloc(sizeof(ptr->next));

    /* Second structure */
    ptr->next->data = 2;
    ptr->next->next = malloc(sizeof(ptr->next->next));

    /* Third structure, why not */
    ptr->next->next->data = 3;
    ptr->next->next->next = NULL;

    printf("ptr->data = %d\n", ptr->data);
    printf("ptr->next->data = %d\n", ptr->next->data);
    printf("ptr->next->next->data = %d\n", ptr->next->next->data);

    return 0;
}

I guess there is a bunch of better ways of doing this, I know that the best way would be maybe to traverse through or declare additional pointers, but what if the constraints don't allow such methods? What would be the overall best way to achieve this?

BTW this is not my HW, just curiosity :)

Have a great day and thx for the tips!

Upvotes: 0

Views: 69

Answers (1)

JeremyP
JeremyP

Reputation: 86661

The first thing that is wrong is this:

structure *ptr = malloc(sizeof(ptr));

That allocates enough space to hold a ptr which is a pointer, you need

structure *ptr = malloc(sizeof(*ptr));

Having allocated everything correctly, access things in the first element like this:

ptr->data; // the data
ptr->next; // pointer to the next struct in the chain

Access stuff in the second struct like this

ptr->next->data; // data in the second struct
ptr->next->next; // pointer to the third struct

And so on.

Having just read some of the comments on the question, I should add that ptr->next->next is inherently dangerous unless you know for a fact that both ptr and ptr->next are non null. Also, malloc doesn't guarantee zeroed memory so after calling malloc you should always ensure that the next pointer is NULL.

If you have a long chain, and the last item is signified by having a NULL next you can iterate through the chain nicely with a for loop e.g.

for (structure* current = ptr ; current != NULL ; current = current->next)
{
    printf("%d\n", current->data);
}

Or, if you want to find the nth item

structure* ptrAtIndex(structure* start, int index) 
{
    for (structure* current = ptr, int i = 0 ; current != NULL ; current = current->next, i++)
    {
        if (i == index)
        {
            return current;
        }
    }
    return NULL; // The chain wasn't long enough
}

Upvotes: 1

Related Questions