2

I made two structs, they are very similar. The first one is a node and the second one, called hash, only contains a pointer to a node. In main I've made pointers to allocated memory for them. newNode points to the node and alfabet to allocated memory for 26 hash structs. I have to use the arrow operator when I assign values to the node. newNode --> value = "lachbal". But when I assign a value to the hash struct I have to use the dot operator otherwise I get an error message : error: member reference type 'struct hash' is not a pointer. Now, when I do not use hash as an array, I can use an arrow (alfabet -> head = newNode). So, it's the index ([]) and the fact I've got 26 of them that does it. Is the index itself a pointer the way a char* is a pointer to the first character of a string? That doesn't explain the EM and I don't understand it. Could you please clarify? Thank you.

struct llnode {
    char value[31];
    struct llnode* next;
};
struct hash { 
    struct llnode* head;
};
int main() {
    struct llnode *newNode = malloc(sizeof(struct llnode));
    struct hash *alfabet = malloc(sizeof(struct hash) * 26);

    strcpy(newNode -> value, "lachbal");
    alfabet[5].head = newNode;             
    for (int i = 0; i < 26; i++) {
        printf("%i %s\n", i, alfabet[i].head ->  value);
    }        

}
6

OK, this is going to be long answer, because what you've asked spans many subjects, so bare with me.

Arrays vs Pointers

First, let's learn the difference between arrays and pointers. When you declare an array as:

int nums[20];

you reserve 20 consecutive places in memory, which you can refer to by the variable nums. Specifically, you reserve these places in stack memory. Stack memory is where all your local variables get stored, and the order with which you called a series of function, so your program knows how to return to the caller function.

When you want those places in memory to be on the heap memory, you use:

int *nums;
nums = malloc(20 * sizeof(int));

Both of these reserve the same amount of memory, but one is on the stack while the other is in the heap memory.

In both cases, can access you can access the elements in the array using any of two notations:

nums[7] = 42;

or

*(nums+7) = 42;

The first uses the array brackets notation, while the second, treats nums as a pointer (which it is in both cases), moves some places forward from that position in memory (the +7 part), and derefrences the memory at that position (the * at the beginning). Here is a complete program you can run to test this:

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

int main(int argc, char const *argv[])
{
    // allocate the memory in stack
    int nums[20];

    // allocate the memory in heap
    int *nums2;
    nums2 = malloc(20 * sizeof(int));

    // array-like notation
    nums[7] = 42;
    nums2[7] = 42;

    // pointer-like notation
    *(nums+8) = 50;
    *(nums2+8) = 50;

    // the two notations can be used interchangeably 
    printf("%d\n", *(nums+7));
    printf("%d\n", *(nums2+7));

    printf("%d\n", nums[8]);
    printf("%d\n", nums2[8]);

    // never forget to free the memory you have allocated in the heap!
    free(nums2);

    return 0;
}

with output:

42
42
50
50

In both cases, you can use any other type of variable, I just used int for simplicity.

You can read more about stack and heap here.

Structs in stack and structs in heap

Now let's see what happens with your structs, for which you allocate memory in stack, but they have variables stored in heap and stack.

Let's start with how you access a struct if it's in heap and how if it's in stack. For example we will use the following struct:

struct test
{
    int foo;
    int *bar;
    int baz[20];
    int *qux;
};

When you want to access a variable of a struct in stack, you use the . operator as in:

t1.foo = 5;

When you want to access a variable of a struct in heap, you use the -> operator, which is the same as *(t2).foo, as in:

t2->foo = 5;
// the same as
*(t2).foo = 5;

We almost always use the arrow notation, because its cleaner and more readable. Here is a working example program of how you access variables in heap and stack inside structs stored in heap and stack:

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

struct test
{
    int foo;
    int *bar;
    int baz[20];
    int *qux;
};

int main(int argc, char const *argv[])
{
    // a test struct stored in stack
    struct test t1;

    // a test struct stored in heap
    struct test *t2 = malloc(sizeof(struct test));

    /**
     * access the struct stored in stack
     */

    // single variable in stack
    t1.foo = 42;

    // single variable in heap
    t1.bar = malloc(sizeof(int));
    *(t1.bar) = 50;

    // array in stack
    t1.baz[7] = 100;

    // array in heap
    t1.qux = malloc(20 * sizeof(int));
    t1.qux[7] = 200;

    /**
     * access the struct stored in heap
     */

    // single variable in stack
    t2->foo = 42;

    // single variable in heap
    t2->bar = malloc(sizeof(int));
    *(t2->bar) = 50;

    // array in stack
    t2->baz[7] = 100;

    // array in heap
    t2->qux = malloc(20 * sizeof(int));
    t2->qux[7] = 200;


    printf("%d\n", t1.foo);
    printf("%d\n", t2->foo);

    printf("%d\n", *(t1.bar));
    printf("%d\n", *(t2->bar));

    printf("%d\n", t1.baz[7]);
    printf("%d\n", t2->baz[7]);

    printf("%d\n", t1.qux[7]);
    printf("%d\n", t2->qux[7]);

    // never forget to free the memory you have allocated in the heap!
    free(t1.bar);
    free(t1.qux);

    free(t2->bar);
    free(t2->qux);
    free(t2);

    return 0;
}

with output:

42
42
50
50
100
100
200
200

Arrays of structs in stack and in heap

Here is also how to have an array of structs in stack and in heap and access them:

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

struct test
{
    int foo;
    int *bar;
    int baz[20];
    int *qux;
};

int main(int argc, char const *argv[])
{

    /**
     * You can also have an array of structs in stack and in heap
     */

    /**
     * Array of structs in stack
     */
    struct test t1[20];

    // single variable in stack
    t1[5].foo = 42;

    // single variable in heap
    t1[5].bar = malloc(sizeof(int));
    *(t1[5].bar) = 50;

    // array in stack
    t1[5].baz[7] = 100;

    // array in heap
    t1[5].qux = malloc(20 * sizeof(int));
    t1[5].qux[7] = 200;

    /**
     * Array of structs in heap
     */
    struct test *t2 = malloc(20 * sizeof(struct test));

    // single variable in stack
    t2[5].foo = 42;

    // single variable in heap
    t2[5].bar = malloc(sizeof(int));
    *(t2[5].bar) = 50;

    // array in stack
    t2[5].baz[7] = 100;

    // array in heap
    t2[5].qux = malloc(20 * sizeof(int));
    t2[5].qux[7] = 200;


    printf("%d\n", t1[5].foo);
    printf("%d\n", t2[5].foo);

    printf("%d\n", *(t1[5].bar));
    printf("%d\n", *(t2[5].bar));

    printf("%d\n", t1[5].baz[7]);
    printf("%d\n", t2[5].baz[7]);

    printf("%d\n", t1[5].qux[7]);
    printf("%d\n", t2[5].qux[7]);

    // never forget to free the memory you have allocated in the heap!
    free(t1[5].bar);
    free(t1[5].qux);

    free(t2[5].bar);
    free(t2[5].qux);
    free(t2);

    return 0;
}

with output:

42
42
50
50
100
100
200
200

I hope this answers your question, which from what I understand is in general about how you access variables inside structs in stack and in heap.

For any further questions, drop a comment bellow.

Happy coding! :)

| improve this answer | |
  • Great examples going beyond even some of the stuff in lectures and shorts. Did you mean to also paste the output for the last segment of code with arrays? Awesome job – dumbitdownjr Jul 19 '17 at 18:55
  • Oh right! It slipped me! Thanks! :) – ChrisG Jul 19 '17 at 19:00
  • These examples are really great. I feel a lot more confident now. I've put all your examples in an html-table for quick reference. Maybe, it could be handy for others as well but I wouldn't know how to attach the file. One small detail. In the section about arrays of structs you have switched the titles Array of structs in heap and array of structs in stack. struct test *t2 = malloc(20 * sizeof(struct test)); is an array of structs in the heap or am I mistaken? – Karin Jul 21 '17 at 21:56
  • You are right. It took me 2 years but I fixed it... :P – ChrisG Oct 4 '19 at 9:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .