Это не будет легче, например, Python, если вы выбираете такой разрозненный дизайн, естественно, будет немного больно управлять, естественно.
Печать будет работать так, как вы говорите, оператор C ->
обычно используется именно так. Конечно, если могут быть указатели NULL, где структура не является «полной», вам необходимо проверить это перед разыменованием указателя, иначе у вас будет неопределенное поведение.
Пополнение, вероятно, лучше всего сделать, написав функции для создания экземпляра на каждом слое, которые затем могут вызывать друг друга в цепочке для настройки самого верхнего типа:
D* d_create(int num);
C* c_create(int num);
B* b_create(int num);
A* a_create(int foo, int num)
{
A* a = malloc(sizeof *a);
if(a != NULL)
{
a->foo = foo;
a->bar = b_create(num);
if(a->bar != NULL)
return a;
free(a);
}
return NULL;
}
Это немного громоздко, поскольку все фактические данные (foo
и num
) должны быть переданы в функцию верхнего уровня, которая создает экземпляр A
, но она работает и очень проста .
Обратите внимание, как мы отлавливаем ошибки от распределителей памяти более низкого уровня, убедившись, что указатель B
не равен NULL
. Такие проверки необходимы и для других create
-функций.