Нулевая инициализация структур, гарантирующих протирание заполненных областей?
Предположим, что у меня есть следующая структура:
typedef struct
{
unsigned field1 :1;
unsigned field2 :1;
unsigned field3 :1;
} mytype;
Первые три бита будут использоваться, но sizeof(mytype)
вернет 4
, что означает 29 бит заполнения.
Мой вопрос заключается в том, что эти биты заполнения, гарантированные стандартом, равны нулю, инициализируются выражением:
mytype testfields = {0};
или
mytype myfields = {1, 1, 1};
Чтобы было безопасно выполнить следующее memcmp()
в предположении, что бит 4..29 будет равен нулю и, следовательно, не повлияет на сравнение:
if ( memcmp(&myfields, &testfields, sizeof(myfields)) == 0 )
printf("Fields have no bits set\n");
else
printf("Fields have bits set\n");
Ответы
Ответ 1
Да и нет. Фактический стандарт C11 указывает:
Если объект, который имеет статическую или длительность хранения потоков, не является инициализируется явно, тогда:
Так что это справедливо только для объектов статического хранилища на первом представлении. Но потом он говорит дополнительно:
Если в списке, заключенном в фигурные скобки, меньше инициализаторов, чем там являются элементами или элементами совокупности или меньше символов в строковый литерал, используемый для инициализации массива известного размера, чем там являются элементами в массиве, остальная часть совокупности должна быть инициализируется неявно так же, как объекты, имеющие статическое хранилище длительность.
Таким образом, это означает, что заполнение внутри подструктур, которые не инициализированы явно, инициализируется нулевым битом.
В обобщении, некоторые дополнения в структуре гарантированно инициализируются нулевым битом, некоторые - нет. Я не думаю, что такая путаница будет преднамеренной, я напишу отчет о дефекте для этого.
В старых версиях этого не было. Поэтому с большинством существующих компиляторов вы должны быть еще более осторожными, так как они еще не реализуют C11. Но AFAIR, clang уже делает от этого имени.
Также имейте в виду, что это выполняется только для инициализации. Заполнение не обязательно копируется при назначении.
Ответ 2
В стандарте C99 не указывается, что биты заполнения будут установлены на ноль. Фактически, в нем конкретно упоминается, что значения любых дополняющих битов не определены, поэтому заполнение не нужно копировать в присваивании.
Сноска 51-6.2.6.1 (6) (n1570):
Таким образом, например, назначение структуры не должно копировать любые биты заполнения.
Новый стандарт C2011 - благодаря Jens Gustedt для обмена этими знаниями - указывает, что биты заполнения в объектах статической или продолжительности хранения потоков без явной инициализации инициализируются до 0.
По-прежнему нет гарантий для назначения.
Ответ 3
Мой вопрос заключается в том, что эти биты заполнения, гарантированные стандартом, равны нулю, инициализируются выражением:
Нет.
Значение отступов неуказано:
(C99, 6.2.6.1p6) "Когда значение хранится в объекте структуры или типа объединения, в том числе в объекте-члене, байты представления объекта, которые соответствуют любым байтам заполнения, принимают неопределенные значения"
РЕДАКТИРОВАТЬ: См. Jens Gustedt answer, теперь C11 гарантирует, что отступы установлены на 0
в (редких) определенных обстоятельствах