Ініціалізація структури до 0


116

Якщо у мене така структура:

typedef struct
{
    unsigned char c1;
    unsigned char c2;
} myStruct;

Який найпростіший спосіб ініціалізувати цю структуру до 0? Чи вистачить наступного?

myStruct _m1 = {0};

або Чи потрібно мені явно попросити кожного члена до 0?

myStruct _m2 = {0,0};

Відповіді:


142

Перший найпростіший ( передбачає менший набір тексту ), і він гарантовано працює, для всіх членів буде встановлено 0[Посилання 1] .
Другий - читабельніший.

Вибір залежить від уподобань користувача або від того, який вимагає ваш стандарт кодування.

[Посилання 1] Довідник C99 Стандарт 6.7.8.21:

Якщо в списку, включеному дужкою, є менше ініціалізаторів, ніж є елементи або члени сукупності, або менше символів у рядковому літералі, що використовується для ініціалізації масиву відомого розміру, ніж у масиві елементів, решта сукупності повинна ініціалізуватись неявно так само, як об'єкти, які мають статичну тривалість зберігання.

Добре читати:
C і C ++: Часткова ініціалізація автоматичної структури


9
Крім того, я використовую = {};Однак я не впевнений, що це дійсно.
Вільям Ентрікен

15
@FullDecent порожні дужки для ініціалізації є розширенням GNU.
a3f

2
@ alias65536 Питання позначено тегом C не C ++.
a3f

3
У мене виникла помилка: "відсутні дужки навколо ініціалізатора [-Werror = відсутні-дужки]", ймовірно, через масив учасників: /
DrumM

3
@Edenia. Я не погоджуюсь. Я вже знаю, що foo = {0}означає. Якби я побачив foo = ZERO_FULL, мені б привітатися з визначенням ZERO_FULL.
Ендрю Бейнбрідж

32

Якщо дані є статичною або глобальною змінною, вона за замовчуванням заповнюється нулем, тому просто оголосіть її myStruct _m;

Якщо дані є локальною змінною або зоною, виділеною купою, очистіть їх memsetтак:

memset(&m, 0, sizeof(myStruct));

Поточні компілятори (наприклад, останні версії gcc) оптимізують це досить добре на практиці. Це працює лише в тому випадку, якщо всі нульові значення (включаючи нульові вказівники та нуль з плаваючою точкою) представлені як усі нульові біти, що вірно на всіх платформах, про які я знаю (але стандарт C дозволяє реалізувати, де це неправда; я не знаю такої реалізації) .

Ви можете, можливо, кодувати myStruct m = {};або myStruct m = {0};(навіть якщо перший член myStructне скалярний).

Я відчуваю, що використання memsetдля локальних структур найкраще, і це краще передає той факт, що під час виконання потрібно щось робити (хоча зазвичай глобальні та статичні дані можна розуміти як ініціалізовані під час компіляції, без витрат на час виконання) .


7
Немає гарантії, що встановлення всіх байтів структури 0буде еквівалентно ініціалізації всіх членів структури, 0хоча. На багатьох платформах це буде правдою, але не універсально.
Сандер Де Дайкер

1
Можете поділитися прикладом, Сандер? Справжня цікавість. (Очевидно, що не є загальновиробничим, це не обов'язково означає виняток, який легко пояснити, але якщо є ...)
Стівен Фішер

2
Стандарт C дозволяє нульовому вказівнику (або нульовому номеру з плаваючою точкою) представляти в пам'яті щось інше, ніж усі нульові біти. Дуже мало і дивних реалізацій роблять це (я не можу назвати жодного).
Базиль Старинкевич

-1, ви можете виявити ініціалізацію, яку ОП запитує про некрасиву, але це саме те, що передбачено стандартом, і це може бути легко оптимізовано всіма компіляторами. Тоді форма {}не є дійсною C, але доступна лише в C ++.
Йенс Гуведт

7
@Steven: Я можу думати лише про незрозумілі та / або старі платформи. C FAQ містить перелік платформ, які мали NULLвказівник, який не був усіма 0бітами: c-faq.com/null/machexamp.html . І тоді існує можливість, що платформа не використовує IEEE 754 для представлення значень з плаваючою комою, але використовує інше представлення, яке не має значення 0бітів, 0.0але, правда, я не знаю такої платформи.
Сандер Де Дайкер

19

Див. § 6..7.9 Ініціалізація:

21 Якщо в списку, включеному дужками, є менше ініціалізаторів, ніж елементів або членів сукупності, або менше символів у рядковому літералі, що використовується для ініціалізації масиву відомого розміру, ніж елементів у масиві, решта сукупності повинні ініціалізуватися неявно такими ж, як об'єкти, які мають статичну тривалість зберігання.

Так, так, вони обоє працюють. Зауважте, що в C99 також може бути використаний новий спосіб ініціалізації, який називається призначеною ініціалізацією:

myStruct _m1 = {.c2 = 0, .c1 = 1};

Найбільше, що це вже C89: open-std.org/JTC1/SC22/WG14/www/docs/n1124.pdf#page=139 (Важливо для конкретних цілей обробки сигналів)
Tobias
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.