Гарантируется ли, что memset обнулит биты заполнения в структуре?

В общем, в соответствии со стандартом C гарантируется, что memset() с 0 обнулит биты заполнения в структуре C?

А как насчет gcc?

Например, что-то вроде:

struct MyStruct
{
    unsigned char   member1;
    unsigned int    member2;
    char        member3;
    unsigned char   member4;
    float       member5;    
};

struct MyStruct ms;

memset(&ms, 0, sizeof( struct MyStruct));

person Lunar Mushrooms    schedule 18.12.2011    source источник
comment
Можете ли вы показать нам пример кода?   -  person Mysticial    schedule 18.12.2011
comment
Я не понимаю, что заставляет вас сомневаться в этом.   -  person MK.    schedule 18.12.2011
comment
Затем короткий ответ: Да. Это обнулит всю область памяти, занятую ms. Прокладки и все такое...   -  person Mysticial    schedule 18.12.2011
comment
@MK, я где-то видел комментарий, в котором нет структур memcmp, хотя вы установили эти структуры перед их использованием. Я подумал, что если биты заполнения уже установлены в 0, то не будет никаких проблем с использованием memcmp позже. Может быть, ссылка, которую я нашел, неверна.   -  person Lunar Mushrooms    schedule 18.12.2011
comment
Я бы подумал, что было бы неплохо не полагаться на memcmp вообще для сравнения ваших структур, потому что, если вы когда-нибудь забудете memset, у вас будет одна неприятная ошибка, которую трудно найти. Поэтому, если не доказано, что это узкое место в производительности, напишите явную функцию сравнения. Также представьте себе ситуацию, когда у вас есть char buf[20], и в одной структуре вы устанавливаете значение aaa, а в другой — bbb, а затем устанавливаете для обеих структур значение c. Структуры теперь логически равны, но memcmp увидит их как разные.   -  person MK.    schedule 18.12.2011
comment
@MK, спасибо. Теперь я понял, почему мы не должны сравнивать структуру даже после того, как memset равен 0.   -  person Lunar Mushrooms    schedule 18.12.2011


Ответы (3)


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

person Gravity    schedule 18.12.2011
comment
Это неправда; все последние компиляторы знают семантику memset и оптимизируют ее, и компилятор, безусловно, действительно знает о том, где находятся отступы. - person saagarjha; 06.09.2020

Да, memset записывает 32-битное значение в непрерывную область памяти заданной длины, начиная с заданного адреса. В вашем случае memset записывает регион с (32-битное значение) 0.

Итак, если вы сделаете memset длины sizeof (your_struct), все будет в порядке:

memset(&ms, 0, sizeof(struct MyStruct));
person jman    schedule 18.12.2011

Если это имеет значение, вы, вероятно, делаете что-то небезопасное и непереносимое.

Да, вызов memset установит любые биты заполнения (или байты) в 0, но в языке нет гарантии, что установка объекта float в значение all-bits-zero установит его в 0.0. То же самое относится и к указателям: не гарантируется, что all-bits-zero будет нулевым указателем. (В обоих случаях это верно для большинства реализаций.)

Первоначальный стандарт ISO C90 или C99 даже не гарантировал, что all-bits-zero является допустимым представлением 0 для целочисленных типов; одно из технических исправлений после C99 добавило такую ​​​​гарантию (только для целочисленных типов).

Для переносимости, если вы хотите, чтобы что-то было равно нулю, установите это явно. Вы также можете воспользоваться преимуществами инициализации с нулевым значением для статических объектов и для пропущенных членов в инициализаторах.

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

person Keith Thompson    schedule 18.12.2011