Home > Mobile >  How does sizeof() work with a dereference?
How does sizeof() work with a dereference?

Time:09-09

A recent code sample i saw:

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

struct x {
       int a;
       int b;
};

int main(void) {

    struct x *ptr = malloc(sizeof(*ptr));
    return 0;
}
  • How does sizeof(*ptr) even work?

  • How can a undefined pointer be dereferenced and be given to sizeof() and yield the correct size? (surely it should result in undefined behavior since its undefined)

  • Lastly does the C standard define this sort of behavior at all? (maybe showing it is legal in C, i could not find anything)

CodePudding user response:

ptr is not actually dereferenced here. The operand of the sizeof operator, in this case the expression *ptr, is looked at only for its type.

This is spelled out in section 6.5.3.4p2 of the C standard regarding the sizeof operator:

The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant

In this particular case, *ptr is not evaluated but it is seen to have type struct x, so sizeof(*ptr) evaluates to a constant which is the size in bytes of struct x.

CodePudding user response:

sizeof is not a function call, it is an operator. It does not work on the value of ptr, but its type. ptr has been declared to be of type struct x* and so the compiler knows that sizeof(*ptr) is equivalent to sizeof(struct x).

Demonstration.

CodePudding user response:

The sizeof operator takes an expression or a parenthesized type as its argument. It does not evaluate its argument unless that argument is a variable length array. Either way, the size is determined from the type of the operand.

So, given a pointer int *p, sizeof *p yields the size of an int since the expression *p has type int. There is no evaluation and hence no dereference here. Alternatively, you could use sizeof(int) to find the size of an int. In the first case the operand is the expression *p, and in the second case the operand is the parenthesized type (int).

It may be worth commenting that struct x *ptr = malloc(sizeof(*ptr)); is a useful C idiom. The parentheses around *ptr are not needed since *ptr is an expression, not a type:

struct x *ptr = malloc(sizeof *ptr);

This construct is clear and easy to maintain when types change, e.g., when struct x is no longer desired, but now struct y is needed, there is only one thing to change:

struct y *ptr = malloc(sizeof *ptr);

After this one simple change ptr is a pointer to struct y, and the correct amount of memory has been allocated for one struct y.

  • Related