Наиболее широко используется для библиотечных целей. Основным принципом непрозрачного типа в c является использование данных через указатель, чтобы скрыть реализацию обработки данных. Поскольку реализация скрыта, вы можете изменить библиотеку, не перекомпилировав какую-либо программу, которая зависит от нее (если интерфейс соблюдается)
например:
Версия 1:
// header file
struct s;
int s_init(struct s **x);
int s_f(struct s *x);
int s_g(struct s *x);
// source file
struct s { int x; }
int s_init(struct s **x) { *x = malloc(...); }
int s_f(..) { ... }
int s_g(..) { ... }
версия 2
// header file
struct s;
int s_init(struct s **x);
int s_f(struct s *x);
int s_g(struct s *x);
// source file
struct s { int y; int x; }
int s_init(struct s **x) { *x = malloc(...); }
int s_f(..) { ... }
int s_g(..) { ... }
С вашей стороны программы ничего не изменилось! и, как было сказано ранее, нет необходимости перекомпилировать каждую программу, которая на него полагается.