Search code examples
cpointersmallocsizeof

Is sizeof(<variable>) instead of sizeof(<type>) always safe?


I know that I can protect myself by writing

int *ptr = malloc(sizeof (*ptr))

instead of

int *ptr = malloc(sizeof (int))

The benefit is that if you decide to change the type of ptr to for instance long* instead of int*, then you only need to change the code at one place.

My question is, is this strategy always safe to do? Is there any situation where the construct T *ptr = malloc(sizeof(*ptr)) would not work? Does it matter if T is some complex struct, pointer to pointer, function pointer or an array? Or a combination of them for that matter.

I have tried to come up with a situation where it causes problems, but to me it seems safe. But I want to be able to trust the code completely.


Solution

  • The only case I could see causing problems is if *ptr has a variable-length array type, because that's the only case where sizeof evaluates its operand.

    That is:

    int n = ...;
    T (*ptr)[n] = malloc(sizeof *ptr);
    

    has undefined behavior because the type of *ptr is T [n], which is a variable-length array type, which means sizeof evaluates its operand, which dereferences an uninitialized pointer (*ptr).

    However, it's hard to run into that issue by accident. Normally you'd just do

    T *ptr = malloc(n * sizeof *ptr);
    

    which is fine1.


    1 Well, the multiplication might overflow. To protect against that, you need something like T *ptr = calloc(n, sizeof *ptr);.