您必须动态分配如此大的数组。这是一种方法:
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 );
编辑
考虑一下,存储 15003 个 4 字节整数大约需要 12.5 Gb;您将无法在 32 位系统上执行此操作(最多只能支持 4 Gb 虚拟地址空间)。您需要一个 64 位系统,但即便如此,您也可能无法在单个连续块中分配那么多空间。
另一种方法是分段分配,如下所示:
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
}
此时,您已经分配了足够的内存来存储 m x m x m 元素;
像任何 3D 数组一样索引,S[i][j][k]。与 3D 阵列不同,单个
行在内存中不相邻 - 您最终会得到如下所示的内容:
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 指向 int ** 的 1500 个元素序列1;每个S[i] 指向int * 的1500 个元素序列;每个S[i][j] 指向int 的1500 个元素序列。
优势 - 没有一块内存那么大(5 到 10 Kb,取决于指针大小)。
缺点 - 行在内存中不相邻,因此您不能使用单个指针“遍历”整个数组,也不能在单个 memcpy 或 fwrite 中复制或序列化数组称呼。
如果发生故障,您需要小心回滚任何部分分配 - 仅释放 S 不会释放您为每个 S[i] 或 S[i][j] 分配的内存。
完成后,您需要按照分配的相反顺序解除分配:
// 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 );
再次假设您的系统可以支持高达 16 GB 的虚拟地址空间(即 64 位)。否则,您将无法建造这么大的结构。
- 我在这里故意使用术语“序列”而不是“数组”,因为
S、S[i] 和S[i][j] 都不是数组因此。这些项目中的每一个都是一个指针,而不是一个数组。