malloc for struct and pointer in C

No, you’re not allocating memory for y->x twice.

Instead, you’re allocating memory for the structure (which includes a pointer) plus something for that pointer to point to.

Think of it this way:

         1          2
        +-----+    +------+
y------>|  x------>|  *x  |
        |  n  |    +------+
        +-----+

So you actually need the two allocations (1 and 2) to store everything.

Additionally, your type should be struct Vector *y since it’s a pointer, and you should never cast the return value from malloc in C since it can hide certain problems you don’t want hidden – C is perfectly capable of implicitly converting the void* return value to any other pointer.

And, of course, you probably want to encapsulate the creation of these vectors to make management of them easier, such as with:

struct Vector {
    double *data;    // no place for x and n in readable code :-)
    size_t size;
};

struct Vector *newVector (size_t sz) {
    // Try to allocate vector structure.

    struct Vector *retVal = malloc (sizeof (struct Vector));
    if (retVal == NULL)
        return NULL;

    // Try to allocate vector data, free structure if fail.

    retVal->data = malloc (sz * sizeof (double));
    if (retVal->data == NULL) {
        free (retVal);
        return NULL;
    }

    // Set size and return.

    retVal->size = sz;
    return retVal;
}

void delVector (struct Vector *vector) {
    // Can safely assume vector is NULL or fully built.

    if (vector != NULL) {
        free (vector->data);
        free (vector);
    }
}

By encapsulating the creation like that, you ensure that vectors are either fully built or not built at all – there’s no chance of them being half-built. It also allows you to totally change the underlying data structures in future without affecting clients (for example, if you wanted to make them sparse arrays to trade off space for speed).

Leave a Comment