Нужно ли мне устанавливать ptr в NULL, если я раньше использую memset? - PullRequest
2 голосов
/ 13 апреля 2020

Например:

struct sth {
    int  t;
    char *p;
    struct sth *next;
}

И код инициализации:

struct sth *data = malloc(sizeof(*data));
memset(data, 0, sizeof(*data));
data->t = 0;        // A
data->p = NULL;     // B
data->next = NULL;  // C

Поскольку я использовал memset, нужно ли мне писать A, B, C?

Это просто пример, у меня есть структура с большим количеством указателей ...

Ответы [ 4 ]

3 голосов
/ 13 апреля 2020

Нет необходимости. Вы также можете использовать calloc() вместо malloc(), он обнулит память без необходимости дополнительного вызова memset() и может быть быстрее .

1 голос
/ 13 апреля 2020

" Нужно ли мне устанавливать ptr на NULL, если я использую memset() раньше? "

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

Цитата из текущего C стандарта ISO: IEC 9899: 2018 (C18), раздел 7.22.3.5/2 - Функция Callo c:

" Пробел инициализируется всеми нулевыми битами. 302) "

" 302 - Обратите внимание, что это не должно совпадать с представлением плавающей нулевая точка или константа нулевого указателя ."


" Поскольку я использовал memset(), нужно ли мне писать A, B, C "?

A. является избыточным, поскольку t не является объектом типа с плавающей запятой, поскольку те могут иметь нулевое значение с плавающей запятой , который может иметь не все биты, установленные на 0. Если бы t было типа float или double A., было бы полезно и уместно соответствовать стандарту.

B. и C. являются подходящими, поскольку в соответствии со стандартной настройкой каждый байт 0 не обязательно также устанавливает указатели на NULL, если вы явно хотите, чтобы они были назначены на NULL (хотя так должно быть в большинстве систем).

Обратите внимание, что calloc() может быть более удобным, а также более быстрым по производительности, поскольку он выделяет память и немедленно инициализирует каждый ее бит в 0:

struct sth *data = calloc(sizeof(*data));

Но, опять же, здесь p и next не обязательно должны быть NULL.

0 голосов
/ 13 апреля 2020

Установка структуры на все нулевые биты с помощью memset() эффективно устанавливает для всех целочисленных элементов значение 0. Стандарт C указывает, что другие члены будут иметь значение, которое может соответствовать или не соответствовать эффекту установки им значения 0 вручную. Но на всех современных архитектурах это так, и кажется маловероятным, что какой-либо новый процессор выйдет из этого соглашения в будущем. Таким образом, на практике вы в безопасности.

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

struct sth *data = calloc(1, sizeof(*data));
0 голосов
/ 13 апреля 2020

Более простая версия:

struct sth *data = malloc(sizeof(*data));
*data = (struct sth){0};

Ваш компилятор может оптимизировать это до вызова callo c, если платформа имеет нулевые биты для членов структуры.

...