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 相比,限定符总是应用于数组类型而不仅仅是元素会不会有伤害?