铸造双*(双)(*)[N]

void compute(int rows,int columns,double *data) {
    double (*data2D)[columns] = (double (*)[columns]) data;
    // do something with data2D
}

int main(void) {
    double data[25] = {0};
    compute(5,5,data);
}

有时,将参数视为多维数组是非常方便的,但它需要被声明为一个指向平面数组的指针.像上面的例子中的计算一样,将指针视为一个多维数组是安全的吗?我很确定内存布局保证正常工作,但我不知道标准是否允许以这种方式投射指针.

这是否会破坏任何严格的混叠规则?指针算术的规则如何?由于数据“实际上不是”一个double [5] [5],我们允许在data2D上执行指针算术和索引,还是违反了指针算术不会偏离适当数组的边界的要求? data2D甚至可以保证指向正确的地方,还是只保证我们可以将其转回并恢复数据?标准报价将不胜感激.

解决方法

我提前道歉,因为有一些模糊的答案,有人说这些规则在标准是很难解释.

C11 6.3.2.3说

A pointer to an object type may be converted to a pointer to a
different object type. If the resulting pointer is not correctly
aligned for the referenced type,the behavior is undefined.

所以实际的转换是很好的,只要这两个指针都具有相同的对齐方式.

然后,通过指针访问实际数据,C11 6.5给你一个关于“别名”的乱码文本墙,这是很难理解的.我会尝试引用我认为是这个具体情况的唯一相关部分:

“The effective type of an object for an access to its stored value is
the declared type of the object,if any.” /–/

“An object shall have its stored value accessed only by an lvalue
expression that has one of the following types:

  • a type compatible
    with the effective type of the object,”

/–/

  • “an aggregate or union type that includes one of the aforementioned types among its
    members”

(以上有时被称为“strict aliasing rule”,这不是正式的C语言术语,而是由编译器实现者组成的术语.)

在这种情况下,对象的有效类型是25倍的数组.您尝试将其转换为一个数组指针,数组为5双打.无论是与有效类型兼容的类型,还是作为包含类型的聚合,我不知道.但我确信它是两种有效的情况之一.

所以据我看,这段代码并没有违反6.3.2.3和6.5.我相信代码保证工作正常,行为应该是明确的.

相关文章

本程序的编译和运行环境如下(如果有运行方面的问题欢迎在评...
水了一学期的院选修,万万没想到期末考试还有比较硬核的编程...
补充一下,先前文章末尾给出的下载链接的完整代码含有部分C&...
思路如标题所说采用模N取余法,难点是这个除法过程如何实现。...
本篇博客有更新!!!更新后效果图如下: 文章末尾的完整代码...
刚开始学习模块化程序设计时,估计大家都被形参和实参搞迷糊...