Programmers tend to approach every problem by first writing more code.  Which then has to be maintained.  Every problem is not a nail...
More code is not the simplest, most effective solution here.  More code is also likely to produce an executable that's slower.
Stack memory is just memory - it's no different from heap memory.  It's just managed by the process differently, and is subject to different resource limits.  There's no real difference to the OS whether a process uses 1 GB of memory on its stack, or 1 GB from its heap.
In this case, the stack size limit is likely an artificial configuration setting.  On a Linux system, the stack size limit can be reset for a shell and its child processes:
bash-4.1$ ulimit -s unlimited
bash-4.1$ ulimit -s
unlimited
bash-4.1$
See this question and its answers for more details.
All POSIX-compliant systems should have similar features, as the stack-size limit is a POSIX-standard resource limit.
Also, you can run a thread with an arbitrarily large stack quite easily:
#include <pthread.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <stdio.h>
void *threadFunc( void *arg )
{
    double array[1024][1024][64];
    memset( array, 0, sizeof( array ) );
    return( NULL );
}
int main( int argc, char **argv )
{
    // create and memset the stack lest the child thread start thrashing
    // the machine with "try to run/page fault/map page" cycles
    // the memset will create the physical page mappings
    size_t stackSize = strtoul( argv[ 1 ] ? argv[ 1 ] : "1073741824",
        NULL, 0 );    
    void *stack = mmap( 0, stackSize, PROT_READ | PROT_WRITE,
        MAP_PRIVATE | MAP_ANON, -1, 0 );
    memset( stack, 0, stackSize );
    // create a large stack for the child thread
    pthread_attr_t attr;    
    pthread_attr_init( &attr );
    pthread_attr_setstacksize( &attr, stackSize );
    pthread_attr_setstackaddr( &attr, stack );
    pthread_t tid;
    pthread_create( &tid, &attr, threadFunc, NULL );
    void *result;
    pthread_join( tid, &result );
    return( 0 );
}
Error checking has been omitted.
This also works if you run ulimit -s unlimited before running the compiled program (and of course if the machine has enough virtual memory...):
#include <string.h>
int main( int argc, char **argv )
{
    double array[1024][1024][64];
    memset( array, 0, sizeof( array ) );
    return( 0 );
}