WedX - журнал о программировании и компьютерных науках

Размер структуры с двумя указателями void равен 4?

я не понимаю почему

struct e{
    void * a;
    void * b[];
}

имеет sizeof(e) == 4, а

struct f{
    void * a;
    void * b;
}

имеет sizeof(f) == 8.

16.09.2010


Ответы:


1

Второй в первой структуре — это не указатель, а FAM — гибкий член массива. Он используется, когда у вас есть длинный буфер и вы помещаете e в начало этого буфера. Затем вы можете проиндексировать оставшуюся память, которая следует за объектом e, используя этот FAM, и рассматривать эту память как массив void*.

Стандарт говорит (выделено мной)

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

Например, следующий код выводит 1 для структуры без, но 4 для структуры с FAM на GCC, потому что для доступа к целым числам FAM необходимо правильно выровнять (в этом примере на границе 4 байта)

struct A {
  char a;
};

struct B {
  char a;
  int flex[];
};

int main() {
  printf("sizeof A: %d\nsizeof B: %d\n", 
         (int)sizeof(struct A),
         (int)sizeof(struct B)
    );

  struct B *b = malloc(sizeof *b + sizeof(int[3]));
  b->a = 'X';
  b->flex[0] = 1;
  b->flex[1] = 2;
  b->flex[2] = 3;
  free(b);
}
16.09.2010
  • Поскольку вы скомпилировали содержимое в разных сообщениях и добавили пример, я принял ваш ответ вместо предыдущего. 16.09.2010

  • 2
    struct e{
        void * a;
        void * b[];
    //          ^^
    }
    

    [] в структуре делает b гибким членом массива C99. Таким образом, sizeof(e) будет учитывать только размер a, который равен 4.

    Из C99 §6.7.2.1/16:

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

    Однако, когда оператор . (или ->) имеет левый операнд, который является (указателем) структурой с гибким элементом массива, а правый операнд называет этот элемент, он ведет себя так, как если бы этот элемент был заменен самым длинным массивом (с тот же тип элемента), который не делал бы структуру больше, чем объект, к которому осуществляется доступ; смещение массива должно оставаться смещением гибкого элемента массива, даже если оно будет отличаться от смещения замещающего массива. Если этот массив не имеет элементов, он ведет себя так, как если бы он имел один элемент, но поведение не определено, если предпринимается какая-либо попытка получить доступ к этому элементу или сгенерировать указатель после него.

    16.09.2010
  • Значит ли это, что я не могу получить к нему доступ? 16.09.2010
  • @Alan: Нет, ты все еще можешь получить доступ к b. 16.09.2010
  • @Алан: нет; это просто означает, что sizeof() возвращает результат, который вы наблюдаете. 16.09.2010
  • @ Алан: Да. Вам нужен компилятор C99, и вам нужно выделить место для структуры за пределами sizeof структуры. Если вы поместите его в стек, доступ к нему будет UB. 16.09.2010
  • Судя по вашим комментариям и размеру записи в Википедии, я понял. Спасибо! 16.09.2010
  • Если у вас есть struct FOO {int32 x,y;}; struct BAR {int32 a,b; FOO dat[];}, and one allocates a BAR *boz` с 36 байтами, можно ли легально получить доступ к boz->dat[3].x? Хотя boz->dat[3] не помещается полностью в выделенное пространство, boz->dat[3].x должно начинаться через 32 байта после начала boz и, таким образом, должно помещаться в выделенное пространство. 06.10.2012

  • 3

    Это связано с тем, что вторая структура использует гибкий массив элементов. Объяснение размера результата находится в Википедии.

    16.09.2010

    4

    void * b[]; недействителен в C89, поэтому это означает, что вы используете компилятор C99.

    C99 ввел средство для определения «структурного хака»: теперь он называется «гибкий элемент массива», и до того, как ему будет выделена память, его размер равен 0.

    16.09.2010
  • Это также было важно отметить, потому что я пытался придерживаться C89. Спасибо! 16.09.2010

  • 5

    Потому что первый не объявляет места для указателей в «b».

    16.09.2010
    Новые материалы

    Как проанализировать работу вашего классификатора?
    Не всегда просто знать, какие показатели использовать С развитием глубокого обучения все больше и больше людей учатся обучать свой первый классификатор. Но как только вы закончите..

    Работа с цепями Маркова, часть 4 (Машинное обучение)
    Нелинейные цепи Маркова с агрегатором и их приложения (arXiv) Автор : Бар Лайт Аннотация: Изучаются свойства подкласса случайных процессов, называемых дискретными нелинейными цепями Маркова..

    Crazy Laravel Livewire упростил мне создание электронной коммерции (панель администратора и API) [Часть 3]
    Как вы сегодня, ребята? В этой части мы создадим CRUD для данных о продукте. Думаю, в этой части я не буду слишком много делиться теорией, но чаще буду делиться своим кодом. Потому что..

    Использование машинного обучения и Python для классификации 1000 сезонов новичков MLB Hitter
    Чему может научиться машина, глядя на сезоны новичков 1000 игроков MLB? Это то, что исследует это приложение. В этом процессе мы будем использовать неконтролируемое обучение, чтобы..

    Учебные заметки: создание моего первого пакета Node.js
    Это мои обучающие заметки, когда я научился создавать свой самый первый пакет Node.js, распространяемый через npm. Оглавление Глоссарий I. Новый пакет 1.1 советы по инициализации..

    Забудьте о Matplotlib: улучшите визуализацию данных с помощью умопомрачительных функций Seaborn!
    Примечание. Эта запись в блоге предполагает базовое знакомство с Python и концепциями анализа данных. Привет, энтузиасты данных! Добро пожаловать в мой блог, где я расскажу о невероятных..

    ИИ в аэрокосмической отрасли
    Каждый полет – это шаг вперед к великой мечте. Чтобы это происходило в их собственном темпе, необходима команда астронавтов для погони за космосом и команда технического обслуживания..


    Для любых предложений по сайту: [email protected]