C99规范第6.7.3.8段规定
如果数组类型的规范包括任何类型限定符,则元素类型是合格的,而不是数组类型.如果函数类型的规范包括任何类型的限定符,则行为未定义.
在基本原理(逻辑页面87,物理页面94)中,给出了将平面指针转换为(可变长度)数组指针的示例.
void g(double *ap, int n) { double (*a)[n] = (double (*)[n]) ap; /* ... */ a[1][2] /* ... */ }
当然,如果数组ap
未在函数内修改,则应将其标记为const,但是应该标记为
void g(const double *ap, int n) { const double (*a)[n] = (const double (*)[n]) ap; /* ... */ }
不保留const
限定符,因为(每6.7.3.8)它适用于目标的元素而不是目标本身,它具有数组类型double[n]
.这意味着如果给出适当的标志(-Wcast-qual
对于GCC),编译器会正确地抱怨.无法const
用C 表示数组类型,但此强制转换非常有用且"正确".该-Wcast-qual
标志对于识别数组参数的误用非常有用,但误报不鼓励使用它.请注意,索引a[i][j]
更具可读性,并且对于许多编译器而言,生成更好的机器代码,ap[i*n+j]
因为前者允许通过较少的分析从内循环中提升某些整数运算.
编译器是否应将此视为特殊情况,有效地将限定符从元素提升到数组类型以确定给定的强制转换是否删除限定符或是否应修改规范?没有为数组类型定义赋值,因此限定符总是应用于数组类型而不仅仅是元素,这与6.7.3.8形成鲜明对比?
这是一个已知问题,过去10年来在comp.std.c中已经多次讨论过.最重要的是,您提交的具体案例目前在标准C中不合法; 您需要删除限定符或不使用指向数组的指针来引用数组中的限定元素.
如果您认为自己有一个好主意可以克服这个问题,可以将其发布给news:comp.std.c
讨论.如果其他人同意这是一个好主意,那么您或其他人可以提交缺陷报告以改变行为(有几个委员会成员经常使用comp.std.c,那么可能正在审查DR的人员的反馈会在提交之前有用).我认为你的提议可能存在一些问题,让限定符影响数组本身,但我不得不考虑一下.