Это - принятое "то", что использование goto является плохой практикой разработки программного обеспечения. Это не делает его верным. Существуют времена, когда goto полезен, особенно при обработке очистки и при портировании от ассемблера.
участники Массива с переменными границами, кажется мне, имеют одно основное использование, первое, что пришло на ум, который отображает форматы данных прежней версии как шаблонные форматы окна на RiscOS. Они были бы в высшей степени полезны для этого приблизительно 15 лет назад, и я уверен, что существуют все еще люди, там имеющие дело с такими вещами, кто нашел бы их полезными.
, Если использование участников массива с переменными границами является плохой практикой, тогда я предлагаю, чтобы все мы пошли, говорят авторам спецификации C99 это. Я подозреваю, что у них мог бы быть различный ответ.
ЧТЕНИЕ ТЩАТЕЛЬНО, КОММЕНТАРИИ НИЖЕ ЭТОГО ОТВЕТА
Как C Стандартизация продвигаются, нет никакой причины использовать [1] больше.
причина я дал бы для того, чтобы не сделать, случается так, что это не стоит того для связи кода с C99 только для использования этой функции.
Дело в том, что можно всегда использовать следующую идиому:
struct header {
size_t len;
unsigned char data[1];
};
, Который является полностью портативным. Тогда можно принять 1 во внимание при выделении памяти для n элементов в массиве data
:
ptr = malloc(sizeof(struct header) + (n-1));
, Если у Вас уже есть C99 как требование для создания кода по какой-либо другой причине или Вы - цель определенный компилятор, я не вижу вреда.
Вы имели в виду...
struct header
{
size_t len;
unsigned char data[];
};
В C, это - общая идиома. Я думаю, что много компиляторов также принимают:
unsigned char data[0];
Да, это опасно, но с другой стороны, это действительно не более опасно, чем нормальные массивы C - т.е. ОЧЕНЬ опасно;-). Используйте его с осторожностью и только при обстоятельствах, где Вам действительно нужен массив неизвестного размера. Удостоверьтесь Вы malloc и освободите память правильно, с помощью чего-то like:-
foo = malloc(sizeof(header) + N * sizeof(data[0]));
foo->len = N;
, альтернатива должна сделать данные просто быть указателем на элементы. Вы можете тогда перевыделение () данные к корректному размеру как требуется.
struct header
{
size_t len;
unsigned char *data;
};
, Конечно, если бы Вы спрашивали о C++, любой из них был бы плохой практикой. Тогда Вы обычно использовали бы векторы STL вместо этого.
В качестве примечания, для совместимости с C89 такая структура должна быть размещена следующим образом:
struct header *my_header
= malloc(offsetof(struct header, data) + n * sizeof my_header->data);
Или с помощью макросов:
#define FLEXIBLE_SIZE SIZE_MAX /* or whatever maximum length for an array */
#define SIZEOF_FLEXIBLE(type, member, length) \
( offsetof(type, member) + (length) * sizeof ((type *)0)->member[0] )
struct header {
size_t len;
unsigned char data[FLEXIBLE_SIZE];
};
...
size_t n = 123;
struct header *my_header = malloc(SIZEOF_FLEXIBLE(struct header, data, n));
Установка FLEXIBLE_SIZE в SIZE_MAX почти гарантирует, что это не удастся:
struct header *my_header = malloc(sizeof *my_header);
Я видел что-то вроде этого: из интерфейса C и реализации.
struct header {
size_t len;
unsigned char *data;
};
struct header *p;
p = malloc(sizeof(*p) + len + 1 );
p->data = (unsigned char*) (p + 1 ); // memory after p is mine!
Примечание: данные не обязательно должны быть последними.