Any statically sized arrays declared globally are going to be part of the program's data segment. Statically sized arrays declared within a function (and not declared with the 'static' keyword; this would make them a global) are going to be put on the stack.
In particular this includes the example that you gave.
int arr[n];
It doesn't matter that n is computed dynamically; arr will still be stored on the stack. This declaration essentially translates to a call to alloca(sizeof(int) * n). All that it does is adjust the stack pointer to make room for the arr array.
The term 'heap' usually refers to the memory that is managed by malloc and new for dynamic memory allocation. In this sense the only memory that is on the heap is the memory allocated through these calls. Of course, it's also possible to create arrays that are neither in the global data section, stack, nor heap using a call like mmap.
So any of the methods can be employed for memory allocation of arrays..