If I do a `typedef` in C or C++, when should I add `_t` at the end of typedef'ed type? [duplicate]
Asked Answered
S

6

53

I am confused when should I add the trailing _t to typedef'ed types?

For example, should I do this:

typedef struct image image_t;

or this:

typedef struct image image;

What are the general rules?

Another example, should I do this:

typdef enum { ARRAY_CLOSED, ARRAY_OPEN, ARRAY_HALFOPEN } array_type_t;

or this:

typdef enum { ARRAY_CLOSED, ARRAY_OPEN, ARRAY_HALFOPEN } array_type;

Please enlighten me.

Thanks, Boda Cydo.

Stenotype answered 12/7, 2010 at 1:42 Comment(6)
Never. Type names ending with a _t are reserved by some standard (not sure which). Though whatever you do, don't do _type_t. Pick _type or _t (or something else), but please don't stack them. That's just silly.Roving
@Chris: Can you find the standard? That's not a problem in ANSI C or C++.Polydipsia
@Billy - A bit of searching and I think it's POSIX. And scrolling down, James McNellis beat me to that one.Roving
@Billy @Chris: I don't have a reference link, sorry; the restriction and the citation can be found in the answer to What are the rules about using an underscore in a C++ identifier?Evildoer
Identifiers that end in _t are reserved in POSIX: opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html. Not that I pay much attention to that (I typedef to names ending in _t pretty often).Translocation
@MichaelBurr that article says "Implementations may add symbols to the headers shown in the following table, provided the identifiers for those symbols either: […] End in the string indicated as a reserved suffix in the table and do not use the reserved prefixes posix_, POSIX_, or POSIX, as long as the reserved suffix is in that part of the name considered significant by the implementation." So the table is saying you may use _t for types defined in ANY header.Bollworm
E
64

In POSIX, names ending with _t are reserved, so if you are targeting a POSIX system (e.g., Linux), you should not end your types with _t.

Evildoer answered 12/7, 2010 at 1:45 Comment(16)
Empirically, you can often get away with it for a long time - but you have no comeback on anybody if you port to a new platform, or a new version of a platform, and find conflicts. So, it is safest not to use the suffix.Matthei
@Jonathan: True. Of course, empirically, you can get away with a lot of things :-PEvildoer
The CUPS API is riddled with types ending with _t; and it targets POSIX systems, and is the base printing system for modern Macs.Quintuplicate
So are lots of broken APIs. That doesn't mean you should copy their bad behavior.Franny
Unless you like refactoring, avoid using the _t suffix.Daphnedaphnis
@R..: I wasn't suggesting one copies their behaviour, just stating that there is a widely used API that has violated this rule for a long time.Quintuplicate
They are reserved by standard C library, rather than POSIX (eg. std::size_t or std::ptrdiff_t defined in cstddef). This shouldn't be a problem, since there are namespaces.Cannula
@doc: The Standard C library does not use C++ namespaces.Quintuplicate
Could you post a more specific reference where POSIX makes this reservation?Edrisedrock
@loan: If you take a look at the 2008 revision of the POSIX spec and search the page for "ANY header," there is an entry in one of the reserved identifiers tables that reserves the suffix "_t"Evildoer
@JamesMcNellis in a table titled "Implementations may add symbols", in other words, implementors may use the _t suffix.Bollworm
@GrahamLee: Right. Thus, the _t suffix is reserved and should not be used for user-defined types.Evildoer
@JamesMcNellis I find it too big a leap of faith from "implementors may use _t anywhere" to "no-one else may use _t". Unless there's a document that specifically reserves _t for POSIX use, I think this table has been misinterpreted.Bollworm
@Bollworm "implementors may use _t anywhere" means that they can define macros with _t, which means any of your uses of _t are subject to macro substitution.Barbule
I agree with @user23743. Indeed, regardless of the precautions you take, you can always have clashes of type names. Especially in a language/standard without namespaces like C.Coston
... :) grep -i "_t;" stdio.hChancy
P
18

I personally despise the _t convention. So long as you are consistent, it really does not matter, however.

Note that (as other answers here indicate) if you are coding to some other standard, such as POSIX, you need to check if it's okay in that standard before using such names.

Polydipsia answered 12/7, 2010 at 1:43 Comment(0)
F
10

When should use use _t? Never? It's reserved by a major standard (POSIX) and even if it's not now, your code might someday be used in a POSIX environment, so using _t is a bad idea.

I would go further to say that over-use of typedef is bad in general. If your type is a struct, union, or enum, use these keywords when you declare variables and it makes your code more clear. Use of typedef is best reserved for when you want to make the underlying type invisible for abstraction/encapsulation purposes. A few great examples from standard C are size_t, int32_t, mbstate_t, and the stdio FILE.

Some of the worst abuses of typedef are by the Windows API (WORD, DWORD, INT, LPSTR etc.) and glib (gint, gchar, etc.). Making duplicates of the standard C types with the same intended usage is only confusing and serves to lock developers into your library/platform by polluting all the code with these nonstandard type names.

Franny answered 12/7, 2010 at 8:12 Comment(14)
agreed on the Windows API part, but not glib, and for that matter Qt as well: when supporting a large amount of platforms, it is necessary to know what types you're dealing with, and a gint/qint could have different underlying types. Also: nobody will force a developer using glib/Qt to use these internal types, as they are just typedefs, you can easily use int instead of gint (of, of course, for your non-exotic platform, they are the same).Michaeu
Unless you can provide real evidence of the usefulness, I claim you're just plain wrong. gint is not defined as any particular size of integer; it's just as arbitrary as int. If the glib API functions need a particular size then they should just use that type: for example int32_t if they need 32bit integers or size_t if they need an object size or array index, etc.Franny
They are reserved by standard C library, rather than POSIX (eg. std::size_t or std::ptrdiff_t defined in cstddef). This shouldn't be a problem, since there are namespacesCannula
@doc, no, C reserves only a specific set of type names, some of which end in _t. POSIX reserves absolutely any name ending in _t for potential future use. In C++ it's probably a non-issue as long as you use the headers that isolate the standard types to a namespace...Franny
Note that the reason the Windows API does this is that the Windows API types are supposed to be their own types; callable from languages other than C. As such, it's API calls cannot be defined in terms of C types. *nix OSes avoid this by telling all non-C languages to go to hell; but non C languages are more prevalent on Windows than on Unix.Polydipsia
@Michaeu Qt is not a case. It uses standard types like int, bool, const char *, etc., whenever possible. Types such as qreal are used when required to solve some problem (Qt manual on qreal: "Typedef for double on all platforms except for those using CPUs with ARM architectures. On ARM-based platforms, qreal is a typedef for float for performance reasons").Cannula
On the typedef-struct/union/enum; I completely agree that adding the prefix struct/union/enum makes the code better and more readable, but on the other hand my irrational side doesn't allow me to use those unnecessary prefixes. I want to use them, but I can't. Help!Haydeehayden
@R.. as Liss mentioned in another comment, POSIX does not fully reserve the _t prefix, rather, it discourages using it (Relevant text: "all conforming applications are required to avoid symbols ending in ‘‘_t’’"). library_name_sub_module_type_name_t cannot be reasonably compared to err_t or struct state regarding namespace pollution.Arria
@YoYoYonnY: I agree with the second half of your comment about severity and practicality, but formally the reservation is a reservation, not a "discouragement". See "are required".Franny
@R.. the wording is very vague, I agree, however, being "required to avoid" is not quite reserving. One could throw _t suffixed typedefs all over the place and compile it into a valid, well defined POSIX-compliant program. To complement, one could NOT typedef any of the reserved keywords/typedefs and expect it to be POSIX-compliant in any way or form.Arria
@YoYoYonnY: There is no such thing as "compile into a...POSIX-compliant program". Compliance is a formal source-level matter, not a matter of whether the compiled program works. If the source does not meet the requirements written in the standard, it's not a conforming program.Franny
@R.. No, conformance is not (just) a source-level matter (That would be pointless). If the source code does meet the requirements given by POSIX, one can expect the compiled program to be conformant too, and behave as expected (For example, fopen can be expected to return a file in binary mode, even when "b" is not given). If this were not the case, then there would be no reason to make your code conformant in the first place (other than the fact that you can now label your source conformant), because then these guarentees that the program behaves as expected would be gone.Arria
@R.. Of course, wheater your POSIX compliant source code actually compiles into a well defined, POSIX-compliant executable is implementation-defined, but that is irrelevant for my point. But just to be pedantic: I was talking about POSIX-compliant compilers.Arria
@YoYoYonnY: This thread is getting way off-topic. Correcting your misunderstanding of what conformance means is a topic that deserves its own question if you want to continue it.Franny
C
6

I use suffixes to increase readability: _t for typedef, and _e for enums since 25/30 years ... sometimes I use _st when typedef defines a struct.

I think that is good practice to get the code be readable and standardized, then I find right to use suffixes! Furthermore, to date, I have not found any POSIX official document stating that the suffix _t is reserved.

Old stdio.h contains _t ... See: grep -i "_t;" stdio.h :) I think POSIX standard is "a little" younger then C!

Chancy answered 12/4, 2015 at 13:19 Comment(1)
This answer mentions reference inside the POSIX Standard: https://mcmap.net/q/17434/-what-does-a-type-followed-by-_t-underscore-t-represent ("all conforming applications are required to avoid symbols ending in ‘‘_t’’").Almswoman
C
0

I am using _t suffix for enums and primitive types to distinguish them from variables. I put them into namespaces, so I don't care about _t reservations.

To justify it. Very often variable name is an allusion to typedefed type. Like std::size_t size;, array_t array etc. I have found that it's easier to pick up decent name for a variable, when type contains _t suffix. It also reminds me that it's a typedefed primitive and not some other beast like class for example.

Cannula answered 12/7, 2010 at 1:54 Comment(3)
size_t size_t = 0; is legal in C - it declares a variable named size_t of the type size_t. The conflict doesn't matter between types and variables.Roving
And then the code readability goes to space. The same applies to size size = 0;.Retroflexion
@Chris Lutz: Have you read "to distinguish from variables"?Cannula
A
0

Pick good names for your types, just like you should with your variables, functions and anything else. A good name doesn't have redundant information embedded in it that makes it harder to read the code -- _t never helps you if you have a good name to begin with.

By the way: typedef image image; doesn't make any sense, since it just makes image a typedef to itself.

Antitype answered 12/7, 2010 at 2:17 Comment(4)
The example he used was typedef struct image image which is useful in C. In C++, struct image variables may be declared image x; but in C, you have to declare them struct image x; so C programmers use the above to simplify struct declaration for commonly used types.Roving
He didn't write typedef image image — he wrote typedef struct image image. It's common in C.Woodwaxen
It's common even to typedef an unnamed struct this way.Retroflexion
@Chuck, Chris Lutz and Spidey: so he did -- oversight on my part.Antitype

© 2022 - 2024 — McMap. All rights reserved.