gpt4 book ai didi

c - 如何在 C 中声明一个非常大的 3 维数组?

转载 作者:行者123 更新时间:2023-11-30 20:10:18 25 4
gpt4 key购买 nike

我正在尝试创建一个 3 维数组S[ ][ ][ ]...

当尺寸较小时例如:

  m=40;  
int S[m][m][m];
memset(S, 0, sizeof(S[1][1][1])*m * m * m); //initialize all the array with 0//
for (i=1 ; i<=m ; i++ ) {
k=1;
for (j=1 ; j<=n ; j++ ) {
if(statement) { //if statment true i put in S array a value//
S[i][i][k]=j; k++;}

效果很好(对于像 S[ 40 ][ 40 ][ 40 ] 这样的小尺寸...当尺寸很大时,例如:

  m=1500;
int S[m][m][m];
memset(S, 0, sizeof(S[1][1][1])*m * m * m);
....
....

我的程序停止工作可能是由于内存使用或类似的原因,我不确定......有什么想法吗?

谢谢。

最佳答案

您必须动态分配这么大的数组。这是一种方法:

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 位系统,但即便如此,您也可能无法在单个连续 block 中分配那么多空间。

另一种方法是进行分段分配,如下所示:

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]指向一个1500个元素的int *序列;每个S[i][j]指向一个1500个元素的int序列。

优点 - 没有单个内存块那么大(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 位)。如果没有,你将无法 build 这么大的建筑。

<小时/>

  1. 我在这里故意使用术语“序列”而不是“数组”,因为 SS[i]S[ i][j] 本身就是数组。这些项目中的每一个都是一个指针,而不是一个数组。

关于c - 如何在 C 中声明一个非常大的 3 维数组?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46508215/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com