The _t usually wraps an opaque type definition.
GCC merely add names that end with _t to the reserved namespace you may not use, to avoid conflicts with future versions of Standard C and POSIX (GNU C library manual). After some research, I finally found the correct reference inside the POSIX Standard 1003.1: B.2.12 Data Types (Volume: Rationale, Appendix: B. Rationale for System Interfaces, Chapter: B.2 General Information):
B.2.12 Data Types
Defined Types
The requirement that additional types defined in this section end in "_t" was prompted by the problem of name space pollution. It is difficult to define a type (where that type is not one defined by POSIX.1-2017) in one header file and use it in another without adding symbols to the name space of the program. To allow implementors to provide their own types, all conforming applications are required to avoid symbols ending in "_t", which permits the implementor to provide additional types. Because a major use of types is in the definition of structure members, which can (and in many cases must) be added to the structures defined in POSIX.1-2017, the need for additional types is compelling.
In a nutshell, the Standard says that there are good chances of extending the Standard types' list, therefore the Standard restricts the _t namespace for its own use.
For instance, your program matches POSIX 1003.1 Issue 7 and you defined a type foo_t. POSIX 1003.1 Issue 8 is eventually released with a newly defined type foo_t. Your program does not match the new version, which might be a problem. Restricting the _t usage prevents from refactoring the code. Thus, if you aim to a POSIX compliancy, you should definitely avoid the _t as the Standard states it.
Side note: personally, I try to stick to POSIX because I think it gives good basics for clean programming. Moreover, I am pretty fond of Linux Coding Style (chapter 5) guidelines. There are some good reasons why not using typedef. Hope this help!
int_tdefined? If it's always defined asint, it's not useful; it's much clearer to useintdirectly. If it's not always defined asint(say, if it could belong intorshort int), then it's a poorly chosen and confusing name. - Keith Thompson