如何在结构(或等效结构)中定义指向可变长度数组 (VLA) 的指针?

Jeo*_*Kim 4 c arrays struct pointers variable-length-array

我在函数中声明了许多指向可变长度数组(VLA)的指针来动态分配二维数组;例如,

int M, N; // have some value
double (*arr1)[N] = calloc(M, sizeof(double [N]));
double (*arr2)[N] = calloc(M, sizeof(double [N]));
double (*arr3)[N] = calloc(M, sizeof(double [N]));
... // so many declarations
Run Code Online (Sandbox Code Playgroud)

因为函数变得很长,所以我尝试将其分成几个函数,每个函数都需要所有指针作为参数。我没有在函数中传递许多东西(这对性能不利),而是声明了一个全局包含所有指针的结构,以减少参数数量:

struct ptrpack {
    int M, N;
    double (*arr1)[N];
    double (*arr2)[N];
    ...
};

// then each function just takes a single struct rather than many pointers
void foo(struct ptrpack p) {
    ...
}
Run Code Online (Sandbox Code Playgroud)

但是,struct 中不允许存在指向 VLA 的指针。如果结构定义位于函数中,则 GCC 扩展允许这样做,但在我的例子中,定义位于全局范围内。

这个问题的最佳解决方案是什么?我强烈喜欢使用指向 VLA 的指针,而不是普通的指针。

Eri*_*hil 7

将结构成员声明为指向未知大小的数组的指针(括号中未提供大小表达式):

\n
double (*arr1)[];\n
Run Code Online (Sandbox Code Playgroud)\n

此类指针与指向可变长度数组的指针兼容,因为指向兼容类型的指针是兼容的 (C 2018 6.7.6.1 2),并且未知大小的数组与具有兼容元素类型的任何数组兼容,根据 6.7.6.2:

\n
\n

为了使两个数组类型兼容,两者都应具有兼容的元素类型,并且如果两个大小说明符都存在,并且都是整数常量表达式,则两个大小说明符应具有相同的常量值\xe2\x80\xa6

\n
\n

由于指针类型不指示数组大小,因此您将无法直接使用这些成员来访问多个维度。例如,如果p是结构,p.arr1[i][j]将产生编译器错误。使用它们的一种方法是将它们分配给包含类型信息的临时变量:

\n
double (*arr1)[p.N] = p.arr1;\n\xe2\x80\xa6 // arr1[i][j] works here.\n
Run Code Online (Sandbox Code Playgroud)\n