В нашем коде у нас было что-то вроде этого:
*(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 мегабайта большой и только когда-либо предназначалась для существования в куче!
Мы прибегли к созданию собственной функции "initialize", которая явно устанавливает членов, но эта уродливая и головная боль обслуживания. Я не считаю memset правильным решением, потому что я не могу знать, что бит-значение 0 является подходящим нулевым значением для типа (nit-picking, я знаю, но вот вы, я не против, компилятор делает это, потому что он может знать)
Что такое "правильный" или, по крайней мере, лучший способ инициализации такой большой структуры?
Чтобы понять, почему я считаю, что memset не является решением: правила инициализации элементов, явно не инициализированных, такие же, как статическая инициализация, и следующие: - Если у него есть тип указателя, он инициализируется нулевым указателем; - Если он имеет арифметический тип, он инициализируется (положительным или без знака) нулем; ...
'memset' установит память на нулевой бит-шаблон, что не обязательно одно и то же. Представьте себе систему, которая не использует числа с плавающей запятой IEEE. Необычно, но поддерживается C. Представление 0.0 не должно означать "all-bits zero", оно может быть удобным для процессора.