Использует участников массива с переменными границами в C плохая практика?

70
задан maxschlepzig 16 September 2017 в 07:27
поделиться

5 ответов

Это - принятое "то", что использование goto является плохой практикой разработки программного обеспечения. Это не делает его верным. Существуют времена, когда goto полезен, особенно при обработке очистки и при портировании от ассемблера.

участники Массива с переменными границами, кажется мне, имеют одно основное использование, первое, что пришло на ум, который отображает форматы данных прежней версии как шаблонные форматы окна на RiscOS. Они были бы в высшей степени полезны для этого приблизительно 15 лет назад, и я уверен, что существуют все еще люди, там имеющие дело с такими вещами, кто нашел бы их полезными.

, Если использование участников массива с переменными границами является плохой практикой, тогда я предлагаю, чтобы все мы пошли, говорят авторам спецификации C99 это. Я подозреваю, что у них мог бы быть различный ответ.

25
ответ дан Manos Nikolaidis 24 November 2019 в 13:30
поделиться

ЧТЕНИЕ ТЩАТЕЛЬНО, КОММЕНТАРИИ НИЖЕ ЭТОГО ОТВЕТА

Как C Стандартизация продвигаются, нет никакой причины использовать [1] больше.

причина я дал бы для того, чтобы не сделать, случается так, что это не стоит того для связи кода с C99 только для использования этой функции.

Дело в том, что можно всегда использовать следующую идиому:

struct header {
  size_t len;
  unsigned char data[1];
};

, Который является полностью портативным. Тогда можно принять 1 во внимание при выделении памяти для n элементов в массиве data:

ptr = malloc(sizeof(struct header) + (n-1));

, Если у Вас уже есть C99 как требование для создания кода по какой-либо другой причине или Вы - цель определенный компилятор, я не вижу вреда.

19
ответ дан Remo.D 24 November 2019 в 13:30
поделиться

Вы имели в виду...

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 вместо этого.

10
ответ дан Roddy 24 November 2019 в 13:30
поделиться

В качестве примечания, для совместимости с 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);
4
ответ дан 24 November 2019 в 13:30
поделиться

Я видел что-то вроде этого: из интерфейса 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! 

Примечание: данные не обязательно должны быть последними.

6
ответ дан 24 November 2019 в 13:30
поделиться
Другие вопросы по тегам:

Похожие вопросы: