C 可以很好地处理 3D 数组:
double data[D0][D1][D2];
...
data[i][j][k] = ...;
尽管对于非常大的数组(例如您的示例),您可能希望动态分配数组,而不是像上面那样将它们声明为 auto 变量,因为 auto 变量的空间(通常 em> 堆栈,但并非总是如此)可能非常有限。
假设您的所有维度在编译时都是已知的,您可以执行以下操作:
#include <stdlib.h>
...
#define DO 100
#define D1 100
#define D2 100
...
double (*data)[D1][D2] = malloc(sizeof *data * D0);
if (data)
{
...
data[i][j][k] = ...;
...
free(data);
}
这将从堆中分配一个 D0xD1xD2 数组,您可以像访问任何常规 3D 数组一样访问它。
如果直到运行时才知道您的尺寸,但您正在使用支持可变长度数组的 C99 编译器或 C2011 编译器,您可以执行以下操作:
#include <stdlib.h>
...
size_t d0, d1, d2;
d0 = ...;
d1 = ...;
d2 = ...;
...
double (*data)[d1][d2] = malloc(sizeof *data * d0);
if (data)
{
// same as above
}
如果您的尺寸直到运行时才知道,并且您使用的编译器不支持可变长度数组(C89 或更早版本,或不支持 VLA 的 C2011 编译器),您'将需要采取不同的方法。
如果需要连续分配内存,则需要执行以下操作:
size_t d0, d1, d2;
d0 = ...;
d1 = ...;
d2 = ...;
...
double *data = malloc(sizeof *data * d0 * d1 * d2);
if (data)
{
...
data[i * d0 * d1 + j * d1 + k] = ...;
...
free(data);
}
请注意,您必须将 i、j 和 k 索引映射到单个索引值。
如果内存不需要是连续的,你可以像这样进行分段分配:
double ***data;
...
data = malloc(d0 * sizeof *data);
if (data)
{
size_t i;
for (i = 0; i < d0; i++)
{
data[i] = malloc(d1 * sizeof *data[i]);
if (data[i])
{
size_t j;
for (j = 0; j < d1; j++)
{
data[i][j] = malloc(d2 * sizeof *data[i][j]);
if (data[i][j])
{
size_t k;
for (k = 0; k < d2; k++)
{
data[i][j][k] = initial_value();
}
}
}
}
}
}
并将其释放为
for (i = 0; i < d0; i++)
{
for (j = 0; j < d1; j++)
{
free(data[i][j]);
}
free(data[i]);
}
free(data);
这不是推荐的做法,顺便说一句;即使它允许您索引data,就好像它是一个 3D 数组,但要权衡的是更复杂的代码,尤其是如果malloc 在分配循环中途失败(那么您必须退出到目前为止您所做的所有分配)。它也可能会导致性能损失,因为不能保证内存被很好地定位。
编辑
至于将这些数据保存在文件中,这取决于您需要做什么。
最便携的是将数据保存为格式化文本,如:
#include <stdio.h>
FILE *dat = fopen("myfile.dat", "w"); // opens new file for writing
if (dat)
{
for (i = 0; i < D0; i++)
{
for (j = 0; j < D1; j++)
{
for (k = 0; k < D2; k++)
{
fprintf(dat, "%f ", data[i][j][k]);
}
fprintf(dat, "\n");
}
fprintf(dat, "\n");
}
}
这会将数据作为浮点数序列写出,每行末尾有一个换行符,每个“页面”末尾有两个换行符。读回数据基本上是相反的:
FILE *dat = fopen("myfile.dat", "r"); // opens file for reading
if (dat)
{
for (i = 0; i < D0; i++)
for (j = 0; j < D1; j++)
for (k = 0; k < D2; k++)
fscanf(dat, "%f", &data[i][j][k]);
}
请注意,这两个 sn-ps 都假定数组有一个已知的、固定的大小,不会随着运行而改变。如果不是这种情况,您显然必须在文件中存储其他数据以确定数组需要多大。也没有类似于错误处理的东西。
我要留下很多 的东西,因为我不确定你的目标是什么。