Является ли это гибким элементом массива в C?
Возможный дубликат:
Гибкие члены массива в C - плохо?
Я прочитал следующий код:
struct hello {
int number;
int data[1];
};
Я знаю, что члены гибкого массива позволяют нам объявить последний элемент как array of unspecified size
как это:
struct hello {
int number;
int data[];
};
В этом struct
последний элемент не определяет размер, так в чем же разница между этими двумя? и что означает первое объявление?
4 ответа
Этот вид массива:
struct hello {
int number;
int data[];
};
имеет смысл только как последний элемент структуры, и только когда вы выделяете структуру из кучи, и обычно так, чтобы поля заголовка содержали реальный размер массива:
struct hello *helloptr = malloc(sizeof (struct hello) + count*(sizeof int));
helloptr->number = count;
Используется для удобного распределения заголовка и буфера данных с помощью одной структуры.
Дополнение: Разница с вашей версией, которая выделяет массив размером 1, sizeof struct hello
будет больше, так как массив выделяется одним элементом вместо undefined= ноль. Это либо тратит впустую память на один элемент, либо усложняет вычисления по размеру, и концептуально немного "некрасиво" (ваш код имеет массив размера 1, когда вы на самом деле имеете в виду "undefined", возможно, даже 0).
В ООП C++ лучше просто обернуть динамически распределенный буфер внутри класса, это действительно "хак".
Это не гибкий элемент массива, но используется в некотором коде, который должен работать со старыми компиляторами или с компиляторами C++.
Использование его в качестве члена гибкого массива может вызвать неопределенное поведение. В реальном коде это должно работать так, как ожидалось, поскольку этот трюк используется в слишком большом количестве кода для компилятора, чтобы делать какие-то неожиданные вещи.
Оба не полностью эквивалентны в C, даже если вы обращаетесь только к первому элементу. Гибкий массив может иметь другое выравнивание, чем массив с фиксированным размером. Так даже sizeof
может дать вам разные результаты для обоих, и вы никогда не должны смешивать эти два варианта в одном и том же коде.
В чем разница между
data[1]
а такжеdata[0]
?
Разницы нет, оба могут быть использованы для реализации гибкой структуры размера.
Раймонд Чен отвечает на это удачно:
Хорошо, вы можете сказать, тогда почему бы не использовать массив нулевой длины вместо массива 1 длины?
Потому что путешествие во времени еще не усовершенствовано.
Массивы нулевой длины не стали легальным стандартом C до 1999 года. Поскольку Windows существовала задолго до этого, она не могла использовать эту функциональность в языке C.
Обратите внимание, что технически оба примера кода не являются допустимым кодом C++. [Ссылка 1] Но большая часть существующего кода использует эту функциональность, и этот код будет работать почти всегда.
[Ссылка 1] Ссылка:
Стандарт C++11: 8.3.4 Массивы
В декларации
T
D
гдеD
имеет формуD1 [ constant-expressionopt] attribute-specifier-seqopt
....... Если присутствует константное выражение (5.19), оно должно быть интегральным константным выражением, и его значение должно быть больше нуля.