tags:

views:

412

answers:

5

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.

+7  A: 

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

EDIT: And please see other answers here ... apparently you're not supposed to ever do it.

Billy ONeal
+22  A: 

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
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
@Jonathan: True. Of course, empirically, you can get away with a lot of things :-P
James McNellis
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
So are lots of broken APIs. That doesn't mean you should copy their bad behavior.
R..
Unless you like refactoring, avoid using the `_t` suffix.
PeterK
@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
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.
doc
@doc: The Standard C library does not use C++ namespaces.
dreamlax
Could you post a more specific reference where POSIX makes this reservation?
Ioan
@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
A: 

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.

doc
`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
And then the code readability goes to space. The same applies to `size size = 0;`.
Spidey
@Chris Lutz: Have you read "to distinguish from variables"?
doc
A: 

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
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
He didn't write `typedef image image` — he wrote `typedef struct image image`. It's common in C.
Chuck
It's common even to typedef an unnamed struct this way.
Spidey
@Chuck, Chris Lutz and Spidey: so he did -- oversight on my part.
Clearer
+1  A: 

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..
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
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..
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
doc
@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..