我想在 C(99) 中做这样的事情:
int n = compute_size_of_matrices();
int T = compute_number_of_matrices();
float matrices[][n][n] = malloc( sizeof(float) * n*n* T ); //[sic!]
观察第一个维度中缺失的尺寸。我想动态地设置维度的大小,以便执行如下操作
/* Load each matrix with the unit matrix */
for( int t = 0; t < T; t++ )
for( int i = 0; i < n; i++ )
for( int j = 0; j < n; j++ )
matrices[t][i][j] = (i==j)?1.:0.;
当然,我可以简单地将“矩阵”分配为一维数组并使用一些索引魔法,但显然上述数组访问模式更方便。特别是,对于编译器来说,这不是什么技术黑魔法,除了记住动态数组大小的一些开销。是否有 GCC 的编译器扩展、某些方言功能或类似功能允许我执行上述操作?
与此相反,为了避免歧义,上述任务的常用 C 代码如下所示:
int n = compute_size_of_matrices();
int T = compute_number_of_matrices();
float* matrices = malloc( sizeof(float) * n*n* T ); //[sic!]
for( int t = 0; t < T; t++ )
for( int i = 0; i < n; i++ )
for( int j = 0; j < n; j++ )
matrices[t*n*n + i*n + j] = (i==j)?1.:0.;
在真实的例子中,单字母变量可能有更多的名字,这很快就会使这样一段代码变得笨拙。
最佳答案
我发现的最好的
保留矩阵的数组大小属性(虽然不是矩阵的列表),并允许您使用 native 索引符号
int n=5, T=2;
float (*a)[n][n] = calloc(T,sizeof(float[n][n])); // <== initializes to 0!
for (size_t t=0; t<T; ++t)
for (size_t i=0; i<n; ++i)
a[t][i][i] = 1.0; // <== only set the 1's
指向二维数组的指针的声明是棘手的部分,但是 calloc
(见下文)会为您处理零初始化,因此您只需设置非零元素。
当然,当您尝试传递这些东西时,有趣的部分就来了……但是如果您小心声明并且使用的是 c99,您可以做出以下任一
void foo(int n, float (*a)[n][n]) {
// ...
}
void bar(int t, int n, float a[t][n][n]) {
// ...
}
工作。 (实际上 gcc
会让你逃脱,除非你使用 -std=c89 -pendantic
...)
次之,但它适用于 ansi-c
您当然可以使传统版本(带有丑陋的手标)更易于阅读。
int n = compute_size_of_matrices();
int T = compute_number_of_matrices();
float* matrices = calloc(T, sizeof(float) * n*n); // <== initializes to 0!
for( int t = 0; t < T; t++ )
for( int i = 0; i < n; i++ )
matrices[t*n*n + i*n + i] = 1; // <== only set the 1's
嗯,这似乎是个好主意...
唉,c不会让你做的
int n=5, T=2;
float matrices[T][n][n] = {}; // <== ***ERROR!!!***
这将使您保持矩阵的“数组性”并且更加清晰。
速度慢吗?
因为 calloc
将使用一些高度优化的系统内存编写器来设置为 0,所以您不会受到很大的速度影响。
关于c - 在 C 中动态设置数组访问模式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7424769/