Paragraph 6.7.3.8 of the C99 spec states
If the specification of an array type includes any type qualifiers, the element type is so-qualified, not the array type. If the specification of a function type includes any type qualifiers, the behavior is undefined.
In the rationale (logical page 87, physical page 94), an example of casting a flat pointer to a (variable length) array pointer is given.
void g(double *ap, int n)
{
double (*a)[n] = (double (*)[n]) ap;
/* ... */ a[1][2] /* ... */
}
Certainly if the array ap
is not modified within the function, it should be marked const, however the cast in
void g(const double *ap, int n)
{
const double (*a)[n] = (const double (*)[n]) ap;
/* ... */
}
does not preserve the const
qualifier since (per 6.7.3.8) it applies to the elements of the target instead of the target itself, which has array type double[n]
. This means that compilers will rightly complain if given the appropriate flags (-Wcast-qual
for GCC). There is no way to denote a const
array type in C, but this cast is very useful and "correct". The -Wcast-qual
flag is useful for identifying misuse of array parameters, but the false positives discourage its use. Note that indexing a[i][j]
is both more readable and, with many compilers, produces better machine code than ap[i*n+j]
since the former allows some integer arithmetic to be hoisted out of inner loops with less analysis.
Should compilers just treat this as a special case, effectively lifting qualifiers from the elements to the array type to determine whether a given cast removes qualifiers or should the spec be amended? Assignment is not defined for array types, so would it hurt for qualifiers to always apply to the array type rather than just the elements, in contrast to 6.7.3.8?