Compliant Solution
In the first compilation module, which is included by the user, the abstract data type is declared as a pointer to a struct. The struct is declared as an incomplete type.
struct string_mx; typedef struct string_mx *string_m;
In the "private" compilation unit struct string_mx
is fully defined but non-visible to a user of the API.
union str_union_t { char *cstr; wchar_t *wstr; }; struct string_mx { size_t size; // This is the size of the string allocation (includes any NULL) // Note that size is the number of characters, not the number of bytes // For strtype == STRTYPE_WSTR, you must multiply size by sizeof(wchar_t) // to compute the number of bytes size_t maxsize; // maximum size of string unsigned char strtype; union str_union_t charset; // set of valid characters union str_union_t str; // the real string };