【发布时间】:2015-12-10 12:10:47
【问题描述】:
这是一种定义 Matrix 类型的方法
typedef struct {
int nr, nc;
double *elem;
} Matrix;
我想定义这个
typedef struct {
int nr, nc;
double elem[nr][nc];
} Matrix;
这很好,因为我不必担心索引。这就是 VLA 一开始就很有用的原因,因为它们只透明地做索引算法容易做的事情。
当然,如果只是因为结构的大小没有很好地定义,上述情况是不可能的。那么,我仍然会很高兴:
typedef struct {
int nr, nc;
double (*elem)[nc];
} Matrix;
现在,矩阵数据存储为指针,就像在非 VLA 情况下一样。但是算术仍然可以由编译器完成。定义只是告诉它是某种指向 double 数据的指针,双精度数排列在宽度为 nc 的数组中。
标准似乎也不允许这样做,我想知道为什么,因为通过转换很容易做到这一点。例如,使用第一个定义(double *),我可以这样做
double get(Matrix *a, int i, int j) {
int nc = a->nc;
double (*p)[nc] = (double (*)[nc])a->elem;
return p[i][j];
}
当然,这里不是很有趣,因为只有一个对 elem 的访问,但如果有很多,它可能是。
所以,我的问题,希望它是主题:禁止第三个定义的真正原因是什么?
我可以想象这很危险,因为不能保证 nc 处理正确的值,但无论如何这对于指针来说都是危险的,所以这看起来不是一个好的理由。
【问题讨论】:
-
问题是,除了包含灵活数组成员的结构体之外,结构体的大小在编译时是固定的,这样编译器就知道如何布局结构体的数组,例如.
-
@JonathanLeffler 这就是第二个定义错误的原因。但是第三个使用指针,所以大小是已知的(双精度不是结构的一部分)。它只是向
double *添加一些信息,以便透明地完成算术。 -
灵活数组成员中类型的大小必须在编译时知道,而不是在您尝试将
nc构建到类型时。 -
@EliasVanOotegem:括号很重要。这是
double *数组和double数组指针之间的区别。 -
@Jean-ClaudeArbaut:
double (*a)[nc]是一个指向一维数组的指针,但你说得对,括号很重要。您的问题是nc不能用作结构中数组的维度,即使它可以与结构外的局部变量或动态分配的变量(数组)一起使用。
标签: c pointers struct variable-length-array