We can see, as expected, that the v2 variable (int
) occupies 4 bytes
and that the p
variable (int
pointer) occupies 8 bytes.
I'm not sure what exactly the source of your expectation is there. The C language does not specify the sizes of int
s or pointers. Its requirements on the range of representable values of type int
afford int
size as small as two 8-bit bytes, and historically, that was once a relatively common size for int
. Some implementations these days have larger int
s (and maybe also larger char
, which is the unit of measure for sizeof
!).
I suppose that your point here is that in the implementation tested, the size of int
is smaller than the size of int *
. Fair enough.
So, if a pointer occupies more than 4 bytes of memory, why we can
store its content in an int
variable?
Who says the code stores the pointer's (entire) content in the int
? It converts the pointer to an int
,* but that does not imply that the result contains enough information to recover the original pointer value.
Exactly the same applies to converting a double
to an int
or an int
to an unsigned char
(for example). Those assignments are allowed without explicit type conversion, but they are not necessarily value-preserving.
Perhaps your confusion is reflected in the word "content". Assignment does not store the representation of the right-hand side to the left-hand object. It converts the value, if necessary, to the target object's type, and stores the result.
In the underlying implementation, does the pointer variables store
only the memory address of another variable, or it stores something
else?
Implementations can and have varied, and so too the meaning of "address" for different machines. But most commonly these days, pointers are represented as binary numbers designating locations in a flat address space.
But that's not really relevant. C specifies that pointers can be converted to integers and vice versa. It also provides integer types intptr_t
and uintptr_t
(in stdint.h
) that support full-fidelity round trip void *
to integer to void *
conversion. Pointer representation is irrelevant to all that. It is the implementation's responsibility to implement the types and conversions involved so that they behave as required, and there is more than one way to do that.
*C actually requires an explicit conversion -- that is, a typecast -- between pointers and integer. The language specification does not define the meaning of the cast-less assignment in the example code, but some compilers do accept that and perform the needed conversion implicitly. My remarks assume such an implementation.