Ahh, this is a good question.
Indeed, it is *the* question, since you were responding to Chris'
recommendation against typedef'ing structs, and since - contrary
to your blithe (a less charitable reader might call it arrogant)
assumption in another post that they should be obvious to any
experienced C programmer - your justifications for the practice
are neither obvious nor obviously true.
I would offer several reasons:
1. (minor) Slight economy of expression - shorter to omit 'struct'.
Economy of expression is not an absolute good. In fact, it's
arguably done significant damage to software on the whole, due to
the proliferation of code that's difficult to maintain due to
unnecessary terseness.
Moreover, it discards information, which makes the code harder to
understand, which is another obstacle to maintenance. Hiding
information in source code is only good when abstraction is
merited; and in such cases, it's redundant to uphold information-
hiding in itself as an advantage.
2. Using a typedef'ed name gives greater flexibility in the choice
of type - if later we want some_type_name to be a 'union' or 'int'
or 'enum', less of the program will need to change as a result.
Very little less, in most cases. When I write code that operates
on a struct, and that struct subsequently becomes a union or an
int or an enum, chances are excellent that the code itself will
have to change. If I am not hiding the type's category behind a
typedef, the implementation will helpfully notify me if I should
neglect to make such changes. If I am, there are plausible
situations where it will not.
3. Greater safety - if the type is defined in a header file (as it
very likely may be), and the header file is not #include'ed, using
some_type_name *x;
will produce an error, whereas
struct some_type_name_struct_tag *x;
need no produce any diagnostic at all. Sometimes the second case is
perfectly easy to figure out, but the first case is *always* easy to
figure out.
This strikes me as far less common than the previous case. If
the type is defined in a header file, then code which should be
including that header probably needs it for other reasons (eg to
supply prototypes for the API associated with the abstract data
type you're hypothesizing - what else are you going to do with a
pointer to an incomplete type, than pass it to some function
which understands it?).
Further, since all struct pointers have the same alignment and
representation, and since your example is only meaningful when
"struct some_type_name_struct_tag" is an incomplete type, I don't see
what damage is done in the case where the translation unit
accidentally declares its own "struct some_type_name_struct_tag *x".
In fact, unless I am mistake, the only effect of such a declaration
is to place "some_type_name_struct_tag" into the struct tag namespace
and to declare a variable x which can be used semantically to hold any
struct's address (syntactic constraints notwithstanding).
4. Natural extension to opaque types
Opaque data types is one of only two cases where I can see any
advantage to typedef'ing structs. (The other is for passing to
va_arg, which is not compatible with the full C type syntax and so
sometimes requires "helper" typedefs.)
Even in the case of opaque data types, however, there are times when
the struct tag is more useful, I would argue. I like to apply some
fairly strict rules for coupling and information sharing among the
modules (translation units) of many of my projects. In many cases
some use pointers to types that are incomplete to them but complete
for other modules. In this case there's no benefit to hiding the
type category; both opaque and completed types are available to all
the developers who might maintain the code.