> Now you have a naming problem. You need a naming convention that every user of the list library must follow, or else their types will be incompatible.
Oh, that's simple: just have empty struct tags.
> And what about typedefs?
The names introduced by the typedefs are irrelevant.
> A and B are typedef-related (their normal forms, obtained by following all typedefs, are the same), lists of A and B will be incompatible unless users agree on a common name.
Huh?
typedef struct { int x; } A;
typedef struct { int x; } B;
typedef struct { header_list header; A payload; } list_of_A;
typedef struct { header_list header; B payload; } list_of_B;
The structs list_of_A and list_of_B are compatible.
Oh, that's simple: just have empty struct tags.
> And what about typedefs?
The names introduced by the typedefs are irrelevant.
> A and B are typedef-related (their normal forms, obtained by following all typedefs, are the same), lists of A and B will be incompatible unless users agree on a common name.
Huh?
The structs list_of_A and list_of_B are compatible.