Поскольку вы спросили;) в C есть один инструмент, позволяющий избежать явного дублирования кода, макросы. Тем не менее, я не вижу способа не повторять хотя бы название типа. Но и в С++ они тоже не могут, так что С как минимум не хуже :)
самое простое я вижу
#define DESIGNATE_NEW(T) \
memcpy(malloc(sizeof(T)), \
&(T const){ __VA_ARGS__ }, \
sizeof(T))
что дало бы
Type *t = DESIGNATE_NEW(Type,
.a = 2,
.b = 3,
.c = 5,
);
это имеет несколько преимуществ.
- Он правильно инициализирует все элементы, даже в архитектурах с нестандартными представлениями
0
для типов с плавающей запятой или указателей.
- В отличие от версии Кейта, это приемлемый «стиль кодирования», поскольку это просто выражение, похожее на инициализацию, и любой должен немедленно визуально зафиксировать, что должен делать второй фрагмент кода.
NB: обратите внимание на const
в макросе, это позволяет свернуть несколько экземпляров составного литерала, если компилятор решит, что это уместно. Также есть возможность иметь вариант, в котором список обозначений является необязательным, см. P99 ниже.
Недостатком является memcpy
, и я был бы счастлив получить задание. Во-вторых, нет проверки на сбой malloc
перед использованием результата, но, вероятно, можно столкнуться с некоторой странностью, чтобы код завершился красиво.
В P99 я иду немного другим путем. Там у нас всегда есть функция инициализации для типа, что-то вроде
inline
Type* Type_init(Type* t, int a, int b, int c) {
if (t) {
*t = (Type const){ .a = a, .b = b, .c = c };
}
return t;
}
которые с помощью магии макросов можно заставить предоставлять аргументы по умолчанию для a
, b
и c
, если они опущены. Затем вы можете просто использовать что-то вроде
Type *t = P99_NEW(Type, 1, 2, 3);
в коде вашего приложения. Это лучше, так как позволяет избежать разыменования указателя при неудачном вызове malloc
. С другой стороны, это снова вводит порядок в инициализаторы, что тоже не идеально.
person
Jens Gustedt
schedule
22.09.2011
malloc
вернулNULL
? - person detly   schedule 01.09.2011calloc
, а затемt->a=2; t->b=3;
... (calloc
просто там, если вы хотите пропустить какие-либо члены, поэтому, если вы знаете, что вы явно установите их все, вы можете использоватьmalloc
точно также) - person R.. GitHub STOP HELPING ICE   schedule 01.09.2011