在 C89 中重写多维 VLA
Rewriting multi-dimensional VLAs in C89
我正在为开源项目重写一堆 C99 VLA,以支持 Visual Studio。所以我有很多语句,比如
void somefunc(double var[r]){...}
我重写为
void somefunc(double *var) {
var = malloc(sizeof(double) * r);
...
free(var);
}
我认为这是执行此操作的正确方法。
问题是我开始看到一些更复杂的 VLA 声明,这让我很困惑。例如:
double *(*var)[length1][length2][length3] = malloc(sizeof(double *[length4][length1][length2][length3]));
所以对我来说,这基本上看起来像一个 5 维数组。
这在 C89 中显然是非法的,因为在 sizeof()
函数中使用了变量。
我对如何重写这个的猜测是:
double *****var = malloc(sizeof(double ****) * length1);
for(int i = 0; i<length1; i++) {
var[i] = malloc(sizeof(double ***) * length2);
for(int j = 0; j<length2; j++) {
var[i][j] = malloc(sizeof(double **) * length3);
for(int k = 0; k<length3; k++) {
var[i][j][k] = malloc(sizeof(double *) * length4);
}
}
}
虽然很乱,但这是我对如何重写上述语句的最佳猜测。这在技术上是否正确,是否有更好的方法来解决这个问题?
这是我的尝试:
double***** var = malloc(sizeof *var * length4);
for (int i = 0; i < length4; ++i)
{
var[i] = malloc(sizeof *var[i] * length1);
for (int j = 0; j < length1; ++j)
{
var[i][j] = malloc(sizeof *var[i][j] * length2);
for (int k = 0; k < length2; ++k)
{
var[i][j][k] = malloc(sizeof *var[i][j][k] * length3);
for (int l = 0; l < length3; ++l)
{
var[i][j][k][l] = NULL;
// var[i][j][k][l] is a double* - you can allocate some room for a double here, or assign the address of an existing variable
}
}
}
}
与你的类似,除了注意我在第一个 malloc
中如何使用 length4
。如果您查看原始声明,var
是指向 double*
的三维数组的 指针 。正如我们可以从右侧的 malloc
调用中推断的那样,为 length4
这样的数组分配了内存,因此您可以将 var
视为 length4
[=38] 的数组=] double*
.
数组
我仍然认为,任何将此类内容放入生产代码中的人都应该当场枪毙(好吧,作为维护者,请原谅)。
在 for
s 中声明变量的 IIRC 是无效的 C89,但您可以将它们移到范围的顶部。
请注意,正如@immibis 在评论中指出的那样,您的第一次转换很可能是错误的; double *var
是函数的参数,这意味着它是按值传递的,因此您在函数内部对其所做的任何更改在外部都是不可见的,最重要的是,您 malloc
一些内存,用它做事,然后 free
它。即使您正在修改传递的指针——这需要参数类型为 double**
——仍然没有必要传递变量,因此您可以在本地独占使用它。您很可能想要 malloc
函数外部的内存并向其传递一个有效的指针(希望是大小)。
我正在为开源项目重写一堆 C99 VLA,以支持 Visual Studio。所以我有很多语句,比如
void somefunc(double var[r]){...}
我重写为
void somefunc(double *var) {
var = malloc(sizeof(double) * r);
...
free(var);
}
我认为这是执行此操作的正确方法。
问题是我开始看到一些更复杂的 VLA 声明,这让我很困惑。例如:
double *(*var)[length1][length2][length3] = malloc(sizeof(double *[length4][length1][length2][length3]));
所以对我来说,这基本上看起来像一个 5 维数组。
这在 C89 中显然是非法的,因为在 sizeof()
函数中使用了变量。
我对如何重写这个的猜测是:
double *****var = malloc(sizeof(double ****) * length1);
for(int i = 0; i<length1; i++) {
var[i] = malloc(sizeof(double ***) * length2);
for(int j = 0; j<length2; j++) {
var[i][j] = malloc(sizeof(double **) * length3);
for(int k = 0; k<length3; k++) {
var[i][j][k] = malloc(sizeof(double *) * length4);
}
}
}
虽然很乱,但这是我对如何重写上述语句的最佳猜测。这在技术上是否正确,是否有更好的方法来解决这个问题?
这是我的尝试:
double***** var = malloc(sizeof *var * length4);
for (int i = 0; i < length4; ++i)
{
var[i] = malloc(sizeof *var[i] * length1);
for (int j = 0; j < length1; ++j)
{
var[i][j] = malloc(sizeof *var[i][j] * length2);
for (int k = 0; k < length2; ++k)
{
var[i][j][k] = malloc(sizeof *var[i][j][k] * length3);
for (int l = 0; l < length3; ++l)
{
var[i][j][k][l] = NULL;
// var[i][j][k][l] is a double* - you can allocate some room for a double here, or assign the address of an existing variable
}
}
}
}
与你的类似,除了注意我在第一个 malloc
中如何使用 length4
。如果您查看原始声明,var
是指向 double*
的三维数组的 指针 。正如我们可以从右侧的 malloc
调用中推断的那样,为 length4
这样的数组分配了内存,因此您可以将 var
视为 length4
[=38] 的数组=] double*
.
我仍然认为,任何将此类内容放入生产代码中的人都应该当场枪毙(好吧,作为维护者,请原谅)。
在 for
s 中声明变量的 IIRC 是无效的 C89,但您可以将它们移到范围的顶部。
请注意,正如@immibis 在评论中指出的那样,您的第一次转换很可能是错误的; double *var
是函数的参数,这意味着它是按值传递的,因此您在函数内部对其所做的任何更改在外部都是不可见的,最重要的是,您 malloc
一些内存,用它做事,然后 free
它。即使您正在修改传递的指针——这需要参数类型为 double**
——仍然没有必要传递变量,因此您可以在本地独占使用它。您很可能想要 malloc
函数外部的内存并向其传递一个有效的指针(希望是大小)。