因此,如果我理解正确,您想要的是三个r
xr
数组(a
、b
和c
),但您希望它们三个都连续存储;本质上,后备存储将是一个 3 x r
xr
数组。
如果r
在编译时大小未知,并且您正在使用 C99 或支持可变长度数组的 C11 实现,则可以执行以下操作:
size_t r = ...;
double (*a)[r] = NULL;
double (*b)[r] = NULL;
double (*c)[r] = NULL;
double (*backing_store)[r][r] = malloc(3 * sizeof *backing_store);
if (!backing_store)
{
// panic and exit
}
a = backing_store[0];
b = backing_store[1];
c = backing_store[2];
然后,您可以使用a
,b
和c
,就好像它们是 的常规r
xr
数组一样double
:
a[i][j] = ...;
printf("%f\n", b[x][y]);
等等
完成后,您只需要释放backing_store
:
free(backing_store);
为什么这行得通?
表达式backing_store
的类型为“指向 的r
-element 数组的r
-element 数组的指针double
。由于表达式backing_store[i]
等价于*(backing_store + i)
,下标运算符隐式取消引用指针,因此表达式的类型为“ r
-element array of r
-element array of double
”。每个, backing_store[0]
,backing_store[1]
和backing_store[2]
是 的r
xr
数组double
。
请记住,在大多数情况下,“- N
element array of T
”类型的表达式被隐式转换(“decays”)为“pointer to T
”类型的表达式,其值是数组中第一个元素的地址。
因此,表达式backing_store[0]
从类型“ r
-element array r
of double
”转换为“pointer to- r
element array of double
”,恰好是 的类型a
,值是第一个子数组的地址(发生与 )相同backing_store
。同样,应用下标运算符隐式地取消引用指针,因此在之后a[i][j]
给出第th 数组的j
第 th 元素。 i
a
如果在编译r
时已知(即,它是一个常量表达式),那么过程是相同的,您不必声明变量r
:
#define R ...
double (*a)[R] = NULL;
double (*b)[R] = NULL;
double (*c)[R] = NULL;
double (*backing_store)[R][R] = malloc(3 * sizeof *backing_store);
if (!backing_store)
{
// panic and exit
}
a = backing_store[0];
b = backing_store[1];
c = backing_store[2];
如果在编译时不知道r
并且您没有可用的可变长度数组(使用 C89 或不支持 VLA 的 C11 编译器),那么它会变得有点混乱。在这里,我们将backing_store
其视为一维数组double
并计算每个子数组的一维下标:
double *a = NULL;
double *b = NULL;
double *c = NULL;
double *backing_store = malloc(3 * r * r * sizeof *backing_store);
if (!backing_store)
{
// panic
}
a = backing_store;
b = backing_store + r * r;
c = backing_store + 2 * r * r;
a[i*r+j] = ...;
printf("%f\n", b[x*r+y]);
同样,您只需要backing_store
在完成后释放:
free(backing_store);
不如使用二维下标漂亮,但它应该可以工作。