【问题标题】:How can I define a pointer to variable length array (VLA) in a struct (or equivalent)?如何在结构(或等效结构)中定义指向可变长度数组(VLA)的指针?
【发布时间】:2020-11-22 23:49:59
【问题描述】:

我在函数中声明了许多指向可变长度数组 (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

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

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) {
    ...
}

但是,struct 中不允许有指向 VLA 的指针。如果结构定义在函数中,则 GCC 扩展允许它,但在我的情况下,定义在全局范围内。

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

【问题讨论】:

  • 您应该能够从指向数组类型的指针中删除Ndouble (*arr1)[]; 等。现在它只是一个指向不确定大小的数组的指针。这对于一维数组很容易;如果您尝试使用多维数组进行此操作,您将面临更多问题。
  • @JonathanLeffler:大小未知。一个大小不确定的数组完全是另外一回事。也许我分配了内存,也许我没有。
  • 顺便说一下,比起double (*arr1)[N] = calloc(M, sizeof(double [N]));,更喜欢double (*arr1)[N] = calloc(M, sizeof *arr1);。前者会自动将大小调整为arr1 的任何类型,因此减少了因编辑一个位置而不是另一个位置或复杂类型描述中的拼写错误而导致的错误。
  • 关于:double (*arr3)[N] = calloc(M, sizeof(double [N])); 这充其量将分配一个指针数组。那是你真正想要的吗?

标签: arrays c pointers struct variable-length-array


【解决方案1】:

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

double (*arr1)[];

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

对于要兼容的两个数组类型,两者都应具有兼容的元素类型,并且如果两个大小说明符都存在,并且都是整数常量表达式,则两个大小说明符应具有相同的常量值……

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

double (*arr1)[p.N] = p.arr1;
… // arr1[i][j] works here.

【讨论】:

    猜你喜欢
    • 2020-01-14
    • 2018-10-20
    • 1970-01-01
    • 1970-01-01
    • 2010-10-05
    • 2023-03-18
    • 1970-01-01
    • 2017-06-03
    相关资源
    最近更新 更多