Search code examples
cpointersstructtypesmember-variables

When does a pointer in C figure out the amount of memory it references?


I've been learning about linked lists and the recursive definition of the node struct has been bugging me

struct node {
    struct node *next;
    int data;
};

I guess I've always imagined that since a pointer is typed, it knows both the beginning address and the amount of memory it can access when it's dereferenced, at the time of declaration. But it can't possibly, since it's declared before an arbitrary amount of other variables which can make the struct of any size. Does it figure it out only when dereferenced, or is there some sort of memory table that gets filled at the end of the struct definition and before the pointer could be used?


Solution

  • Edit

    Derp. Now I understand the question you're actually asking.

    There are two parts to this. First, the compiler allows you to create pointers to "incomplete" types, where the size isn't yet known. Secondly, all pointers to struct types have the same size and representation, regardless of the size of the actual struct type.

    Going by your example:

    struct node {
        struct node *next;
        int data;
    };
    

    When the compiler sees the declaration for next, the type struct node is incomplete - the compiler doesn't yet know how big struct node will be. However, at this point in the process, it doesn't need to know that size in order for you to declare a pointer to that type. You're not yet at a point where the compiler needs to know sizeof *next.

    The type definition is complete when the compiler sees the closing }; of the struct definition - at that point, the compiler knows how big the struct node type actually is.

    Original

    The compiler knows the size of the pointed-to type, so given a pointer p, the expression p + 1 will yield the address of the next object of the pointed-to type.

    Given

    int    *ip = 0x1000; // 4 bytes
    char   *cp = 0x1000; // 1 byte
    double *dp = 0x1000; // 8 bytes
    

    the expression ip + 1 will yield the address of the next 4-byte int object, or 0x1004, cp + 1 will yield the address of the next 1-byte char object, or 0x1001, and dp + 1 will yield the address of the next 8-byte double object, or 0x1008.

    The pointer itself points to a single object, period. It has no way of knowing whether the object it's pointing to is part of a sequence, or how large any such sequence would be.