professional pro
professional pro

Reputation: 98

How does sizeof() work with a dereference?

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;
}

Upvotes: 4

Views: 770

Answers (3)

ad absurdum
ad absurdum

Reputation: 21321

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.

Upvotes: 1

dbush
dbush

Reputation: 224082

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.

Upvotes: 4

Schwern
Schwern

Reputation: 164919

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.

Upvotes: 2

Related Questions