Пункт 6.7.3.8 состояний спецификации C99
Если спецификация типа массива включает в себя квалификаторы любого типа, тип элемента является так качественно, а не типом массива. Если спецификация типа функции включает в себя квалификаторы любого типа, поведение не определено.
В rationale (логическая страница 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?