Pedantically speaking, from the perspective of the C standard, all the objects involved here simply occupy some memory that is suitably aligned, and disjointed from other objects.
While the notion of a stack and heap are commonplace, the C standard makes no reference to either terms. How and where data is stored is mostly implementation-defined.
The principle thing differentiating them is their visibility and effective lifetimes (see: Storage duration, Lifetime, and Scope):
Practically speaking, however, it is generally fair to refer to objects with
- automatic storage duration as existing on the "stack",
- static storage duration as existing in the "data segment", and
- allocated storage duration as existing on the "heap",
as this a very common way C implementations work.
With this terminology, the object designated by the identifier ptr
exists on the stack, and the objects accessed via the pointer returned by malloc
exist on the heap.