You’ll have to allocate such a large array dynamically. Here’s one method:
m = 1500;
int (*S)[m][m] = calloc( m, sizeof *S );
if ( !S )
{
fprintf( stderr, “Fatal: unable to allocate array\n” );
exit( EXIT_FAILURE );
}
for ( i = 0; i < m; i++ )
{
k = 0;
for ( j = 0; j < m; j++ )
{
if ( expr )
{
S[i][i][k++] = j;
}
}
}
free( S );
Edit
Thinking about it, it takes on the order of 12.5 Gb to store 15003 4-byte integers; you won't be able to do that on a 32-bit system (which can only support up to 4 Gb virtual address space). You'd need a 64-bit system, but even then it's possible you won't be able to allocate that much space in a single, contiguous block.
An alternative is to do a piecemeal allocation, like so:
bool success = true;
size_t i, j;
m = 1500;
int ***S = calloc( m, sizeof *S );
if ( !S )
// bail out here
// Breadth-first allocation strategy, we allocate all a[i] first,
// make sure they all succeeded, and *then* allocate each a[i][j].
for ( i = 0; success && i < m; i++ )
{
S[i] = calloc( m, sizeof *S[i] );
success = (S[i] != NULL );
}
// If allocating any S[i] failed, free all S[0] through S[i-1], *then*
// free S. Freeing S alone won't free each S[i].
if ( !success )
{
while ( i-- )
{
free( S[i] );
}
free( S );
// bail out here
}
// for each S[i], allocate S[i][j].
for ( size_t i = 0; success && i < m; i++ )
{
for ( size_t j = 0; success && j < m; j++ )
{
S[i][j] = calloc( m, sizeof *S[i][j] );
success = (S[i][j] != NULL );
}
}
// Same deal - if any S[i][j] allocation failed, free all S[i][0] through
// S[i][j-1], *then* free all S[0] through S[i], *then* free S.
if ( !success )
{
do
{
while ( j-- )
free( S[i][j] );
free( S[i] );
} while ( i-- );
free( S );
// bail out here
}
At this point, you've allocated enough memory to store m
x m
x m
elements;
index as you would any 3D array, S[i][j][k]
. Unlike a 3D array, individual
rows are not adjacent in memory - you wind up with something that looks like this:
int *** int ** int * int
+---+ +---+ +---+ +---+
S:| | ------> | | S[0] ------> | | S[0][0] --------> | | S[0][0][0]
+---+ +---+ +---+ +---+
| | S[1] | | S[0][1] | | S[0][0][1]
+---+ +---+ +---+
... ... ...
+---+ +---+ +---+
| | S[m-1] | | S[0][m-1] | | S[0][0][m-1]
+---+ +---+ +---+
S
points to a 1500-element sequence1 of int **
; each S[i]
points to a 1500-element sequence of int *
; and each S[i][j]
points to a 1500-element sequence of int
.
Advantage - no single chunk of memory is that big (5 to 10 Kb, depending on pointer sizes).
Disadvantage - rows are not adjacent in memory, so you can't just "walk" through the whole array with a single pointer, and you can't copy or serialize the array in a single memcpy
or fwrite
call.
You want to be careful to roll back any partial allocations in case of a failure - just freeing S
won't free memory you allocated for each S[i]
or S[i][j]
.
When you're done, you'll need to deallocate in the reverse order that you allocated:
// free in reverse order of allocation
for ( i = 0; i < m; i++ )
{
for ( j = 0; j < m; j++ )
free( S[i][j] );
free( S[i] );
}
free( S );
Again, this assumes your system can support upwards 16 GB of virtual address space (i.e., 64-bit). If not, you won't be able to build structures this large, period.
- I'm deliberately using the term "sequence" instead of "array" here, since none of
S
, S[i]
, nor S[i][j]
are arrays as such. Each of those items is a pointer, not an array.