2016-05-08 6 views
2

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

Был struct sigaction, который был первым memset() всем байт ноль с помощью следующей строки:

memset(&sa, 0, sizeof(sa)); 

И я не знаю, почему автор использует этот подход.

+0

Нет. Но вы должны инициализировать переменную перед ее использованием. – Olaf

+0

У _null pointers_ не гарантируется двоичное представление всего бита нуль. Аналогично для членов с плавающей запятой. Так что 'memset' - плохая идея. – Olaf

+0

memset для инициализации структур иногда встречается в старом коде, который был написан до того, как составные литералы стали доступны на C99. – dpi

ответ

3

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

Если вы знаете все элементы структуры и собираетесь их инициализировать явно, то memset() не требуется. Это может быть управляемо, если структура находится под вашим контролем - вам просто нужно помнить, что все места, где происходит инициализация, обновляются при добавлении новых членов в структуру. Если вы напишете функцию для этого (подумайте «аналог C конструктора C++», в первом приближении), то memset() можно оставить без внимания. Если вы установите значения ad hoc во многих местах, у вас, вероятно, возникнут проблемы, если структура изменится.

В случае чего-то вроде struct sigaction это из системного заголовка, а различные системы могут (и делать) добавлять дополнительные поля в структуру - сверх тех, которые вы планируете инициализировать. Обратите внимание, что POSIX указывает только те поля, которые должны присутствовать; он не диктует порядок полей и не требует, чтобы в структуре не было других полей. Тем не менее, функции, использующие дополнительные (не POSIX) элементы структуры, не должны делать этого, если пользователь не указывает, что эти элементы инициализированы, как правило, с некоторым явным флагом, поэтому вы не должны сталкиваться с проблемами - но это лучше безопасно чем жаль.

Следовательно, в условиях, когда у вас нет контроля над структурой, подход memset() легко защищен: гарантируется нулевая вся структура, даже биты, о которых вы не знаете, даже если структура (увеличивается) после того, как код написан.

Вы можете быть в состоянии использовать struct sigaction sa = { 0 }; или struct sigaction *sap = calloc(sizeof(*sap), 1); нуль структуры вместо этого - это отчасти зависит от того, как суетливой набор опций компилятора вы используете (а также версию компилятора вы используете, GCC изменила свое поведение в течение время, например).

Возможно, вы захотите найти макросы, такие как PTHREAD_MUTEX_INITIALIZER, в стандарте POSIX, или вы можете вообще игнорировать их существование.

1

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

struct sigaction sa = {0}; 

таким образом вызов функции сохраняется, и это легко для читателя кода, чтобы определить ее инициализации.

+0

Что такое «инициализационное соединение»? Это даже не _компонентный литерал_, а просто _initialiser_. – Olaf

+0

@ Олаф спасибо, я имел в виду инициализатор структуры. – fluter

+0

Это не является специальным для 'struct': 'int i = {0};' – Olaf

1

Когда вы объявляете struct без инициализатора, это неопределенное поведение, чтобы использовать любой из этих struct членов, не назначая их в первую очередь. Если вы хотите разместить нули во всех членах struct, memset обеспечивает хороший подход для этого.

Если вы все равно назначаете все элементы struct, вызов memset не нужен.

+0

Нет необходимости использовать _initialiser_, чтобы установить переменную в четко определенные значения. – Olaf

Смежные вопросы