The standard describes the various storage durations at §6.2.4
1 An object has a storage duration that determines its lifetime. There
are four storage durations: static, thread, automatic, and allocated.
Allocated storage is described in 7.22.3.
2 The lifetime of an object is the portion of program execution during
which storage is guaranteed to be reserved for it. An object exists,
has a constant address, and retains its last-stored value
throughout its lifetime. If an object is referred to outside of its
lifetime, the behavior is undefined. The value of a pointer becomes
indeterminate when the object it points to (or just past) reaches the
end of its lifetime.
6 For such an object that does not have a variable length array type,
its lifetime extends from entry into the block with which it is
associated until execution of that block ends in any way. (Entering an
enclosed block or calling a function suspends, but does not end,
execution of the current block.) If the block is entered recursively,
a new instance of the object is created each time. The initial value
of the object is indeterminate. If an initialization is specified for
the object, it is performed each time the declaration or compound
literal is reached in the execution of the block; otherwise, the value
becomes indeterminate each time the declaration is reached.
So you are pretty much correct. It doesn't at all describe when and how storage is deallocated per se. It only specifies when that storage is accessible with well-defined semantics. An implementation need not deallocate the storage of a variable with automatic storage duration right away, you just can't touch it if you want your program to be standard compliant.
For allocated storage the same goes, with the added caveat that you have to explicitly tell the implementation you are done with the storage. But even if you do "free" it, an implementation may hold on to it still for a while longer.
It's possible on paper for a very poor implementation to exist, one which never deallocates memory. But in practice, those are culled naturally because poor implementations of C just become disused by the masses, and abandoned.
test, that will be deallocated at function exit. The memory allocated bymallocis taken from heap and is permanent memory (until not explicetly deallocated).