sizeof() структура с элементом массива нулевой длины
Я не понимаю sizeof()
вывод на C. Скажем, у меня есть:
struct foo {
char a;
char b;
char c;
char d[0];
};
Я ожидал sizeof(struct foo)
равным 4. Однако он возвращает 3 после компиляции с помощью gcc. Также при компиляции кода со строгими настройками-pedantic-errors
, Я получаю ошибки компилятора.
Может ли кто-нибудь помочь мне понять это поведение?
2 ответа
Размер массива 0 недопустим. Раздел 6.7.6.2p1 стандарта C, касающийся деклараторов массивов, гласит:
В дополнение к необязательным квалификаторам типа и ключевому слову static,
[
а также]
может ограничивать выражение или*
. Если они ограничивают выражение (которое определяет размер массива), выражение должно иметь целочисленный тип. Если выражение является постоянным выражением, оно должно иметь значение больше нуля. Тип элемента не должен быть неполным или функциональным. Необязательные квалификаторы типа и ключевое слово static должны появляться только в объявлении параметра функции с типом массива и только тогда в самом внешнем производном типа массива.
Так как это нарушает ограничение, это определение вызывает неопределенное поведение.
При этом некоторые компиляторы допускают использование массива нулевой длины в качестве последнего члена struct
как расширение. GCC делает это. В этом случае он работает так же, как гибкий член массива.
Стандартный способ сделать это - оставить поле размера пустым:
struct foo {
char a;
char b;
char c;
char d[];
};
В обоих случаях элемент гибкого массива не включается в размер структуры, поэтому вы получаете 3 для размера вместо 4 (хотя наличие заполнения в структуре зависит от реализации). Это также означает, что такая структура не может быть членом массива (по крайней мере, без некоторых подозрительных манипуляций с указателем вручную).
Вы могли бы использовать такую структуру, чтобы динамически выделять для нее пространство плюс ряд элементов последнего члена. Например:
struct foo *my_foo = malloc(sizeof(*my_foo) + (sizeof(char) * number_of_elements));
char d[0]
представляет собой массив символов с размером 0. Это означает, что он не занимает места, поскольку sizeof(char) * 0 = 0
.