There appears to be a typo in your example not (* int), but (int *).
1) Yes, one way of doing it is through the heap. However this assumes that the parent function will free.
foo()->
{ bar() { malloc} return to foo
free
}
So now you have malloc of a pointer in one function and free in another. Potential for introducing additional bugs (what if you forgot to free in foo ? )
So typically you get foo to allocate the array and pass in the pointer.
2) Alternatively you can statically or globally allocate the array. You are still returning a pointer. But now that pointer is pointing to an array that is in the global data segment.
static int arr[10];
return arr;
Typically any variable you declare in a function is reclaimed at the end of the function.
Static variables are similar to global declarations. There is one copy that persists through the duration of the program. So there is no harm in returning a pointer to that.