Неполный тип массива - это ссылка на местоположение, где был бы выделен первый элемент массива, но фактически не выделяет место для этого элемента. На некоторых старых компиляторах Си можно получить аналогичный эффект, объявив массив нулевого размера, хотя это никогда не было законным ни в одной «официальной» версии стандарта Си. Основное использование для таких объявлений - для структур, которые будут распределены с использованием malloc, calloc или другого подобного механизма; код, который выделяет пространство для структуры, выделит достаточно дополнительного пространства для обработки нужного количества элементов массива.
Прежде чем незавершенные объявления массива стали легальными в C, обычным обходным решением было объявить массив размера 1, а затем вычесть один из числа элементов, добавляемых в структуру. Например:
struct {
int this,that,whatever;
char name[1];
} MYSTRUCT;
void test(char *new_name, int new_name_length)
{
MYSTRUCT *ms = malloc(sizeof(MYSTRUCT)+new_name_length-1);
memcpy(ms->name, new_name, new_name_length);
}
Однако у этого подхода есть несколько неприятных аспектов:
- Нет гарантии, что используемая формула не выделит лишнего дополнительного пространства. Например, если sizeof (int) == 4, sizeof (mystruct) может быть дополнен до 20 байтов из-за требований int-alignment. Если name_length равно четырем, общий размер должен быть 24 байта, но malloc запросит 27.
- Поскольку максимальный допустимый индекс для массива меньше размерного размера или выделенного пространства, доступ к `ms-> name [i]` для любого значения `i`, отличного от нуля, технически будет неопределенным поведением. Таким образом, было бы совершенно законно, если компилятор оптимизировал `ms-> name [i]` как `ms-> name [0]`. На практике я не удивлюсь, если каждый существующий опубликованный компилятор C будет воздерживаться от выполнения этой оптимизации при подписке одноэлементного массива в конце структуры с косвенным доступом (потому что является ли общая реализация структуры struct hack 'легален, его использует много производственного кода.
Если бы компиляторы C просто не включили код для отклонения массивов нулевого размера, и стандарт указал, что максимальное значение индекса для любого массива (unsigned int) (size-1), взломать структуру было бы намного чище , К сожалению, стандарт не был написан таким образом.