所以,如果我理解正确的话,你想要的是三个 r x r 数组(a、b 和 c),但你希望它们三个都连续存储;本质上,后备存储将是一个 3 x r x r 数组。
如果r 的大小在编译时未知并且您正在使用支持可变长度数组的 C99 或 C11 实现,您可以执行以下操作: p>
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,就好像它们是 double 的常规 rxr 数组一样:
a[i][j] = ...;
printf("%f\n", b[x][y]);
等等。
完成后,只需释放backing_store:
free(backing_store);
为什么会这样?
表达式backing_store的类型为“指向r的指针-r的元素数组-double的元素数组。由于表达式backing_store[i]等价于*(backing_store + i),因此下标运算符隐式取消引用指针,所以表达式的类型是“r-元素数组r-元素数组double”。每个backing_store[0]、backing_store[1]和backing_store[2]都是rx@ 987654352@double 的数组。
请记住,在大多数情况下,“N-T 的元素数组”类型的表达式被隐式转换(“衰减”)为“指向T”的类型的表达式,其值为数组中第一个元素的地址。
因此,表达式backing_store[0]从类型“r-元素数组r-元素数组double”转换为“指向r的指针-元素数组double”,即恰好是a的类型,值是第一个子数组的地址(恰好和backing_store一样)。同样,应用下标运算符隐式地取消引用指针,因此a[i][j] 在a 之后给出ith 数组的jth 元素。
如果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 或 C11 编译器) VLA),那么它会变得有点混乱。这里我们将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);
不像使用二维下标那样漂亮,但它应该可以工作。