В нашем коде у нас было что-то вроде этого:
*(controller->bigstruct) = ( struct bigstruct ){ 0 };
Раньше это прекрасно работало, а затем мы обновили версии GCC и неожиданно начали видеть переполнение стека. Глядя на сборку, старый код GCC (2.x) в основном делал это:
memset(controller->bigstruct, 0, sizeof(struct bigstruct));
Новый GCC (3.4.x) делал это
struct bigstruct temp = { 0 };
controller->bigstruct = temp;
После просмотра спецификации C99 я понял, почему; C99 в основном требует наличия анонимных структур в стеке. Это хорошая концепция, но эта структура была размером 4 мегабайта и предназначалась только для кучи!
Мы прибегли к созданию собственной функции инициализации, которая явно устанавливает членов, но это уродливо и головной болью при обслуживании. Я не считаю memset правильным решением, потому что я не могу знать, что значение бита, равное 0, является подходящим нулевым значением для типа (выбор нит, я знаю, но вы есть; я не возражаю против этого это делает компилятор, потому что он может знать)
Каков «правильный» или, по крайней мере, лучший способ инициализации такой большой структуры?
Чтобы пояснить, почему я думаю, что memset не является решением: правила инициализации элементов, не инициализированных явно, такие же, как статическая инициализация, и заключаются в следующем:
- если он имеет тип указателя, он инициализируется нулевым указателем;
- если он имеет арифметический тип, он инициализируется нулем (положительным или без знака);
...
'memset' установит в памяти нулевой битовый шаблон, что не обязательно одно и то же. Представьте себе систему, которая не использует числа с плавающей точкой IEEE. Необычно, но поддерживается C. Представление 0.0 не должно означать «все биты ноль», это может быть что угодно для процессора.