Заполнение структуры C при инициализации

У меня есть такая структура, как

typedef struct
{
    int a;  // Let's say this ends up being 4 bytes
    int b;  // 4 bytes
    char text[10]; // 10 bytes
} blah_t;

static blah_t myvar;
  1. Предположим, что сумма размеров полей составляет 18 байтов в blah_t, но sizeof(blah_t) равно 20 из-за заполнения.
  2. myvar является статическим, поэтому он будет инициализирован нулем.

Вопрос:

  1. Байты заполнения 19 и 20 гарантированно равны 0 для статической переменной? Если нет, мне нужно будет сделать memset(&myvar, 0, sizeof(blah_t)), чтобы любой memcmp структуры был действительным — даже для статической переменной.
  2. А calloc(1, sizeof(blah_t))? Байты 19 и 20 гарантированно равны нулю? Я думаю, что это так.

person B. Nadolson    schedule 13.03.2013    source источник


Ответы (3)


Из стандарта ISO C99: «Когда значение хранится в объекте типа структуры или объединения, в том числе в объекте-члене, байты представления объекта, соответствующие любым байтам заполнения, принимают неуказанные значения».

При дальнейшем рассмотрении здесь обсуждаются некоторые дополнительные вопросы: Сравнение структур в C и C++

РЕДАКТИРОВАТЬ: не дубликат этого вопроса как таковой, а множество общих проблем с подробными ответами.

person Randy Howard    schedule 13.03.2013
comment
Хорошо цитировать стандарт; можете ли вы дать «главу и стих» (какой раздел, какой абзац)? В C2011 (ISO/IEC 9899:2011) это находится в §6.2.6 Представления типов и в подразделе §6.2.6.1 Общие положения, параграф 6. - person Jonathan Leffler; 13.03.2013
comment
Хороший вопрос, я имел в виду и пропустил это. 6.2.6.1 Представления типов, пункт 6. - person Randy Howard; 13.03.2013
comment
Я не вижу дублирования вопроса о С++, который вы упомянули. Классы C++ — это другое животное. Что я надеюсь выяснить... если где-то в спецификации описано, как инициализируются статические переменные для данного конкретного случая. - person B. Nadolson; 13.03.2013
comment
В нем явно говорится, что значения заполнения имеют неуказанные значения, поэтому вы не можете доверять memcmp() в переносимости. - person Randy Howard; 13.03.2013
comment
В обоих случаях запуск программы происходит, когда назначенная функция C вызывается средой выполнения. Все объекты со статической продолжительностью хранения должны быть инициализированы, когда среда выполнения вызывает назначенную функцию C. Все объекты со статической продолжительностью хранения должны быть инициализированы (установлены их начальные значения) перед запуском программы. В остальном способ и время такой инициализации не указаны. ‹‹ Таким образом, может показаться, что заполнение даже для статической структуры не определено. - person B. Nadolson; 13.03.2013
comment
Этот ответ может быть обновлен для изменений C11. Биты заполнения устанавливаются равными нулю, если статическая переменная не инициализируется явно. Я добавил ответ - person afk; 14.08.2019

Принятый ответ Рэнди Ховарда больше не совсем точен с C11.

Байты заполнения 19 и 20 гарантированно равны 0 для статической переменной?

  1. В C11 да, биты заполнения устанавливаются в ноль, когда статическая переменная не инициализируется явно. Стандарт C11, пункт 6.7.9, пункт 10:

. . . Если объект с статическим значением длительности хранения потока не инициализирован явно, то: . . . если это агрегат, каждый член инициализируется (рекурсивно) в соответствии с этими правилами, и любое заполнение инициализируется нулевыми битами . . .

  1. Да, calloc обнулит весь sizeof (включая заполнение) структуры.

Другие полезные и связанные ссылки:

person afk    schedule 14.08.2019

Байты заполнения 19 и 20. Гарантировано ли, что они равны 0 для статической переменной?

См. ответ Рэнди Ховарда.

А как насчет calloc(1, sizeof(blah_t))? Байты 19/20 гарантированно равны нулю?

да. calloc обнуляет память.

Из любопытства мне интересно, почему вы заботитесь о набивке. Переносимый код не должен заботиться о каких-либо аспектах представления (заполнение, порядок следования байтов и т. д.).

person autistic    schedule 13.03.2013
comment
Я хочу memcmp статическую структуру вместо структуры, которая была выделена через calloc. Я знаю, что поведение заполнения не определено, когда речь идет о хранилище, но статически выделенная структура может или не может считаться хранилищем в спецификации. Очень техническое отличие, которое я ищу, да. - person B. Nadolson; 13.03.2013
comment
не имеет значения для переносимости, но может иметь значение для безопасности. Информация может быть просочилась из стека для автоматически выделенных переменных, заполнение которых не было инициализировано. - person Nick Desaulniers; 07.12.2016