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

Внутренний механизм sizeof в C?

Я использую sizeof для получения размера структуры в C, но результат, который я получил, неожиданен.

struct sdshdr {
    int len;
    int free;
    char buf[];
};


int main(){
    printf("struct len:%d\n",(sizeof(struct sdshdr)));
    return 0;
} //struct len:8, with or without buf

мой вопрос в том, почему buf не занимает какое-либо пространство и почему размер типа int все еще 4 на 64-битном процессоре?

вот результат от gcc -v:

Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 6.1.0 (clang-602.0.53) (based on LLVM 3.6.0svn)
Target: x86_64-apple-darwin14.4.0
Thread model: posix  
4b9b3361

Ответ 1

Элемент [] является гибким элементом массива. Они не учитывают общий размер структуры, поскольку стандарт C явно говорит так:

6.7.2.1/18

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

Это преднамеренно по дизайну, поскольку цель гибкого члена массива состоит в том, чтобы позволить вам динамически выделять данные для отслеживания после структуры. (Когда struct является заголовком файла, заголовком протокола и т.д.)

Пример, в том числе обсуждение нестандартных расширений gcc и старого предварительного взлома структуры "C99".

Ответ 2

Начиная с C99, размер массива в конце структуры может быть опущен. Для целей sizeof(struct) этот массив будет иметь нулевой размер (хотя его присутствие может добавить некоторое дополнение к структуре), но цель состоит в том, чтобы его длина была гибкой, т.е. При распределении пространства для структуры необходимо выделить желаемое количество дополнительного пространства для массива в конце. (Чтобы избежать выхода за пределы, фактическая выделенная длина массива должна быть где-то сохранена.)

До C99 было довольно распространенным хаком иметь массив размером 1 (или 0, если разрешено компилятором) в конце структуры, а затем выделить для него больше места, поэтому C99 сделала эту практику явно разрешенной путем введения гибкий элемент массива без заданного размера.

Ответ 3

Как расширение GNU c, у вас есть массивы нулевой длины:

Как расширение GNU, количество элементов может быть как ноль. Массивы с нулевой длиной полезны как последний элемент структуры, который действительно является заголовком для объекта переменной длины:

например, рассмотрите этот код из Руководство по gnu c

 struct line
 {
   int length;
   char contents[0];
 };

 {
   struct line *this_line = (struct line *)
     malloc (sizeof (struct line) + this_length);
   this_line -> length = this_length;
 }

В ISO C99 вы должны использовать гибкий элемент массива, который немного отличается в синтаксисе и семантике:

  • Элементы гибкого массива записываются как содержимое [] без 0.

  • Элементы гибкого массива имеют неполный тип, поэтому оператор sizeof не может применяться. Как причуда исходной реализации массивов нулевой длины, sizeof оценивается до нуля.

  • Элементы гибкого массива могут отображаться только как последний элемент структуры, который в противном случае не пуст.

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

Ответ 4

buf здесь flexible array member Элементы гибкого массива имеют неполный тип, поэтому оператор sizeof не может применяться, тогда как оригинальная реализация zero-length arrays, sizeof evaluates to zero.