По самому проекту тебе ответил уже
Владимир Дубровин, а вот по малой части надо стремиться к декомпозиции (разложению) на исполнители.
В одном .h файле описываешь интерфейс объекта, например, стека
void stack_start();
int stack_push(int value);
int stack_pop();
int stack_isempty();
int stack_topr();
int stack_topw(int value);
void stack_del();
void stack_end();
Дальше в .c файле пишешь реализации этих методов (сами функции и статические (закрытые в файле) переменные, которые им нужны для внутренней работы). И потом, чтобы подключить стек, ты просто подключаешь его .h файл и используешь эти методы.
(Это пример; на самом деле, делается набор методов, который можно применять к разным стекам, где соответствующий стек (структура) просто передаётся в метод первым аргументом.)
В результате у тебя проект (модуль, законченная часть) должен состоять из таких исполнителей, взаимодействующих друг с другом через такие методы.
Тогда всё будет чисто, это всё можно будет тестировать ясными unit-тестами, можно будет легко выделять такую часть и заменять на другую и, самое главное, можно будет сами эти методы также декомпозировать дальше, так как не всегда они просто устроены, как в примере со стеком.