Подтвердить что ты не робот

Объявление нераспределенного массива в структуре

Почему C разрешает это:

typedef struct s
{
  int arr[];
} s;

где массив arr не имеет указанного размера?

4b9b3361

Ответ 1

Это функция C99, называемая гибкими массивами, основная особенность которой заключается в том, чтобы позволить использовать массив переменной длины, например функции внутри структуры и R.. в этом ответе на другой вопрос о гибких членах массива, предоставляет список преимуществ использования гибких массивов над указателями. Проект стандарта C99 в разделе 6.7.2.1 конструкции и союза в пункте 16 гласят:

В качестве особого случая последний элемент структуры с более чем одним именованным элементом может иметь неполный тип массива; это называется гибким элементом массива. В большинстве ситуаций гибкий элемент массива игнорируется. В частности, размер структуры выглядит так, как если бы гибкий элемент массива был исключен, за исключением того, что он мог иметь более длинное дополнение, чем подразумевалось бы упущение. [...]

Поэтому, если у вас есть s* вы выделили бы пространство для массива в дополнение к пространству, требуемому для структуры, обычно у вас были бы другие члены в структуре:

s *s1 = malloc( sizeof(struct s) + n*sizeof(int) ) ;

проект стандарта действительно имеет поучительный пример в пункте 17:

ПРИМЕР После объявления:

  struct s { int n; double d[]; };

структура struct s имеет элемент гибкой матрицы d. Типичный способ использования:

   int m = /* some value */;
   struct s *p = malloc(sizeof (struct s) + sizeof (double [m]));

и предполагая, что вызов malloc преуспевает, объект, на который указывает p ведет себя для большинства целей, как если бы p был объявлен как:

    struct { int n; double d[m]; } *p;

(есть обстоятельства, при которых эта эквивалентность нарушается, в частности, смещения члена d могут быть не одинаковыми).

Ответ 2

Вероятно, вы ищете гибкие массивы на C99. Элементы гибкого массива являются членами неизвестного размера в конце структуры/объединения.

В качестве частного случая последний элемент структуры с более чем одним именованный элемент может иметь неполный тип массива; это называется гибкий элемент массива. В большинстве ситуаций гибкий элемент массива игнорируется. В частности, размер структуры выглядит так, как если бы гибкий элемент массива был исключен, за исключением того, что он может иметь больше это означает, что будет означать прокрутку на конец, чем упущение.

Вы также можете рассмотреть причину struct hack.

Не понятно, является ли оно законным или портативным, но оно довольно популярно. Реализация метода может выглядеть примерно так:

    #include <stdlib.h>
    #include <string.h>

    struct name *makename(char *newname)
    {
        struct name *ret =
            malloc(sizeof(struct name)-1 + strlen(newname)+1);
                    /* -1 for initial [1]; +1 for \0 */
        if(ret != NULL) {
            ret->namelen = strlen(newname);
            strcpy(ret->namestr, newname);
        }

        return ret;
    }

Эта функция выделяет экземпляр структуры имен с помощью размер скорректирован таким образом, чтобы наменное поле могло содержать запрошенное имя (а не только один символ, как предполагает объявление структуры).

Несмотря на свою популярность, техника также несколько известна - Деннис Ритчи назвал его "необоснованным chumminess с реализацией C". Официальная интерпретация сочла, что это НЕ строго соответствует стандарту C, хотя, похоже, он работает при всех известных реализациях. Компиляторы, проверяющие границы массива осторожно могут выдавать предупреждения.