Структурировать нулевые методы инициализации - PullRequest
3 голосов
/ 08 апреля 2019

Есть

struct datainfo info = { 0 };

так же, как

struct datainfo info;
memset(&info, 0, sizeof(info));

Какая разница и что лучше?

Ответы [ 3 ]

6 голосов
/ 08 апреля 2019

Первый способ является лучшим для страны, так как он гарантирует, что struct члены инициализируются так, как если бы они были для static хранилища. Это также понятнее.

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

(Обратите внимание, что в C ++ поведение второго способа вполне может быть undefined . Да, C - это не C ++, а справедливый биткода на C, как правило, в конечном итоге переносится на C ++.)

4 голосов
/ 08 апреля 2019

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

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

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

Лично я предпочитаю инициализацию, а не вызов memset.Потому что это происходит в момент объявления, а не в другом утверждении, не говоря уже о аспекте переносимости.Это делает невозможным случайное добавление кода между ними, что делает инициализацию не запущенной (хотя маловероятной, что это может быть), или как-то неисправной.Но некоторые могут сказать, что memset понятнее даже программисту, читающему его позже, который не знает, как работает {0}.Я не могу полностью игнорировать их аргумент.

1 голос
/ 08 апреля 2019

Как отмечают другие, код является функциональным эквивалентом. Использование компилятора gcc 8.3 x86-64

код:

#include <string.h>
main()
{
    struct datainfo { int i; };
    struct datainfo info;

    memset(&info, 0, sizeof(info));
}

производит сборку:

main:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        lea     rax, [rbp-4]
        mov     edx, 4
        mov     esi, 0
        mov     rdi, rax
        call    memset
        mov     eax, 0
        leave
        ret

пока код:

main()
{
    struct datainfo { int i; };
    struct datainfo info = {0};
}

компилируется в:

main:
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], 0
        mov     eax, 0
        pop     rbp
        ret     

На мой неопытный взгляд, два выхода - это 11 инструкций против 6 инструкций, поэтому, по крайней мере, пространство более эффективно во второй реализации. Но, как отмечают другие, метод нулевой инициализации гораздо более явный в своем намерении.

...