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.

bodacydo
  • 75,521
  • 93
  • 229
  • 319
  • 25
    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. – Chris Lutz Jul 12 '10 at 01:43
  • @Chris: Can you find the standard? That's not a problem in ANSI C or C++. – Billy ONeal Jul 12 '10 at 01:45
  • 3
    @Billy - A bit of searching and I think it's POSIX. And scrolling down, James McNellis beat me to that one. – Chris Lutz Jul 12 '10 at 01:47
  • 1
    @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?](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier/228797#228797) – James McNellis Jul 12 '10 at 01:49
  • 14
    Identifiers that end in `_t` are reserved in POSIX: http://www.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). – Michael Burr Jul 12 '10 at 01:50
  • 2
    @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. –  Apr 11 '13 at 08:43

6 Answers6

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.

James McNellis
  • 348,265
  • 75
  • 913
  • 977
  • 7
    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. – Jonathan Leffler Jul 12 '10 at 02:14
  • 2
    @Jonathan: True. Of course, empirically, you can get away with a lot of things :-P – James McNellis Jul 12 '10 at 02:19
  • 1
    The [CUPS API](http://www.cups.org/documentation.php/doc-1.4/api-ppd.html) is riddled with types ending with `_t`; and it targets POSIX systems, and is the base printing system for modern Macs. – dreamlax Jul 12 '10 at 05:24
  • 11
    So are lots of broken APIs. That doesn't mean you should copy their bad behavior. – R.. GitHub STOP HELPING ICE Jul 12 '10 at 08:05
  • 1
    Unless you like refactoring, avoid using the `_t` suffix. – PeterK Jul 12 '10 at 08:22
  • 1
    @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. – dreamlax Jul 12 '10 at 08:55
  • 1
    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. – mip Jul 12 '10 at 15:47
  • 6
    @doc: The Standard C library does not use C++ namespaces. – dreamlax Jul 13 '10 at 01:17
  • 1
    Could you post a more specific reference where POSIX makes this reservation? – Ioan Jul 14 '10 at 17:07
  • 3
    @loan: If you take a look at [the 2008 revision of the POSIX spec](http://www.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html) and search the page for "ANY header," there is an entry in one of the reserved identifiers tables that reserves the suffix "_t" – James McNellis Jul 14 '10 at 17:11
  • 1
    @JamesMcNellis in a table titled "Implementations may add symbols", in other words, implementors _may_ use the `_t` suffix. –  Apr 11 '13 at 08:44
  • 1
    @GrahamLee: Right. Thus, the `_t` suffix is reserved and should not be used for user-defined types. – James McNellis Apr 11 '13 at 20:06
  • 4
    @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. –  Apr 12 '13 at 05:46
  • 4
    @user23743 "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. – bames53 May 20 '14 at 17:34
  • 1
    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. – Noldorin Feb 08 '15 at 22:56
  • ... :) grep -i "_t;" stdio.h – Sir Jo Black Apr 12 '15 at 13:09
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.

Billy ONeal
  • 104,103
  • 58
  • 317
  • 552
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.

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711
  • 2
    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 `typedef`s, you can easily use `int` instead of `gint` (of, of course, for your non-exotic platform, they are the same). – rubenvb Jul 12 '10 at 09:41
  • 8
    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. – R.. GitHub STOP HELPING ICE Jul 12 '10 at 09:50
  • 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 – mip Jul 12 '10 at 23:06
  • 1
    @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... – R.. GitHub STOP HELPING ICE Jul 13 '10 at 05:21
  • 2
    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. – Billy ONeal Apr 13 '12 at 17:19
  • 3
    @rubenvb 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"). – mip Feb 25 '14 at 13:04
  • 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! – 2501 Feb 01 '16 at 10:23
  • 1
    @R.. as Liss mentioned in another comment, POSIX does not fully reserve the `_t` prefix, rather, it [discourages](http://stackoverflow.com/questions/231760/what-does-a-type-followed-by-t-underscore-t-represent/12727104#12727104) 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. – yyny Oct 19 '16 at 16:46
  • @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". – R.. GitHub STOP HELPING ICE Oct 19 '16 at 16:52
  • @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. – yyny Oct 19 '16 at 17:09
  • @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. – R.. GitHub STOP HELPING ICE Oct 19 '16 at 17:13
  • @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. – yyny Oct 19 '16 at 17:28
  • @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. – yyny Oct 19 '16 at 17:32
  • @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. – R.. GitHub STOP HELPING ICE Oct 19 '16 at 17:46
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!

Sir Jo Black
  • 2,024
  • 2
  • 15
  • 22
  • 3
    This answer mentions reference inside the POSIX Standard: http://stackoverflow.com/a/12727104/1404081 ("all conforming applications are required to avoid symbols ending in ‘‘_t’’"). – Lissanro Rayen Jun 13 '16 at 04:40
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.

mip
  • 8,355
  • 6
  • 53
  • 72
  • 1
    `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. – Chris Lutz Jul 12 '10 at 02:16
  • 5
    And then the code readability goes to space. The same applies to `size size = 0;`. – Spidey Jul 12 '10 at 02:26
  • 3
    @Chris Lutz: Have you read "to distinguish from variables"? – mip Jul 12 '10 at 09:33
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.

Clearer
  • 2,166
  • 23
  • 38
  • 3
    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. – Chris Lutz Jul 12 '10 at 02:19
  • 2
    He didn't write `typedef image image` — he wrote `typedef struct image image`. It's common in C. – Chuck Jul 12 '10 at 02:20
  • 1
    It's common even to typedef an unnamed struct this way. – Spidey Jul 12 '10 at 02:27
  • @Chuck, Chris Lutz and Spidey: so he did -- oversight on my part. – Clearer Jul 12 '10 at 03:53