Поскольку это непрозрачная структура, цель всех этих действий, очевидно, состоит в том, чтобы реализовать непрозрачный тип данных, сохранив при этом все «плюсы» и победив хотя бы некоторые из их «минусов».
Одна существенная проблема с непрозрачными типами данных заключается в том, что в стандартном C вы по существу вынуждены динамически размещать их в непрозрачной библиотечной функции.Невозможно неявно объявить непрозрачный объект локально.Это отрицательно влияет на эффективность и часто вынуждает клиента осуществлять дополнительное управление ресурсами (т. Е. Не забывать освобождать объект, когда он больше не нужен).Предоставление точного размера непрозрачного объекта (в данном случае через функцию) и использование alloca
для выделения хранилища максимально приближены к более эффективному и довольно беззаботному локальному объявлению.
Если время жизни всей функции не требуется, alloca
можно заменить на VLA, но авторы, вероятно, не хотели / не могли использовать VLA.(Я бы сказал, что использование VLA еще больше приблизит эмуляцию к истинному локальному объявлению.)
Часто для реализации того же метода непрозрачный размер объекта может быть представлен как константа времени компиляции взаголовочный файлОднако использование функции имеет дополнительное преимущество, заключающееся в том, что нет необходимости перекомпилировать весь проект, если размер объекта в этой изолированной библиотеке изменяется (как @R. Отмечено в комментариях).
Предыдущая версияответ (пункты ниже все еще применимы, но, очевидно, являются вторичными):
Это не совсем эквивалентно, поскольку alloca
не соответствует правилам времени жизни на основе области действия.Время жизни alloca
-едной памяти распространяется до конца функции, тогда как время жизни локального объекта распространяется только до конца блока.Это может быть плохо, это может быть хорошо в зависимости от того, как вы его используете.
В таких ситуациях, как
some_type *ptr;
if (some condition)
{
...
ptr = /* alloca one object */;
...
}
else
{
...
ptr = /* alloca another object */;
...
}
, разница в семантике может быть решающей.Является ли это вашим случаем или нет - я не могу сказать из того, что вы опубликовали до сих пор.
Другое несвязанное различие в семантике состоит в том, что memset
обнулит все байты объекта, тогда как = { 0 }
не гарантируется обнуление байтов заполнения (если есть).Это может быть важно, если объект затем используется с некоторыми двоичными API (например, отправляется в сжатый поток ввода-вывода).