Является ли это гибким элементом массива в 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 Массивы

В декларации TD где D имеет форму

D1 [ constant-expressionopt] attribute-specifier-seqopt

....... Если присутствует константное выражение (5.19), оно должно быть интегральным константным выражением, и его значение должно быть больше нуля.

Другие вопросы по тегам