4

I've gone down a rabbit hole of questions about typedef, tag and struct namespaces, and leading _ being reserved by either the system libraries or the compilers. My question:

What is the best practice for typedef'ing structs?

For example, here are some possibilities:

typedef struct ll_item {...} ll_item;
typedef struct _ll_item {...} ll_item;
typedef struct ll_item {...} ll_item_type;
typedef struct ll_item {...} LLItemType;

Anyone have experience in which is typically used, and most standard? I've seen textbooks use the leading underscore method for the structure name itself (and I would intuitively use that method as well), but could that pollute that namespace if a system struct uses that name?

user129393192
  • 797
  • 1
  • 8
  • How about `typedef struct LLItem {...} LLItem;`? That's the style used in Apple's code, e.g. for the `CGPoint`, `CGSize`, `CGVector`, and `CGRect` structures, where CG represents the core graphics module. – user3386109 Jun 09 '23 at 07:25
  • 1
    Leading underscores can be tricky. In some contexts symbols defined with a leading underscore are reserved and should not be used, in other they're not. Similarly with trailing `_t`, in some contexts such symbol names are reserved and in other they're not. Better avoid both of them altogether to be safe. – Some programmer dude Jun 09 '23 at 07:28
  • Other than that, there's no variant that is "most standard", it's all up to the programmer or the company to set the rules. It's basically a matter of personal preferences, and hence very subjective. – Some programmer dude Jun 09 '23 at 07:30
  • 1
    There is also the opinion that you should not use typedefs except in special cases: https://www.kernel.org/doc/html/v4.10/process/coding-style.html#typedefs – julaine Jun 09 '23 at 07:42
  • 1
    @julaine Also note the professional rationale with "arguments" such as "Not so" and "NEVER EVER use a typedef". That garage hobbyist hacker document is completely worthless as C programming reference outside Linux programming. Similar could be said about the whole Linux kernel code base. – Lundin Jun 09 '23 at 08:26
  • @Lundin An question asking for possible opinionated pros and cons of something can only be answered somewhat objectively by listing noteable opinions, and I do believe the coding style of the Linux Codebase is a notable opinion. – julaine Jun 09 '23 at 10:10
  • @julaine It's exactly that - a document based on opinions, and there lies the problem. Whereas professional coding standards like CERT and MISRA are based on reputable references, studies, standards/books etc. Whereas the Linux kernel coding style is using the same juvenile argumentation as the average Torvalds tantrum: various flavours of "But I don't want to!" and "You are dumb!" etc... – Lundin Jun 09 '23 at 10:37
  • I always go for `typedef struct ll_item {...} ll_item;` – user16217248 Jun 21 '23 at 23:42

1 Answers1

2

This is all rather subjective. An identifier with a leading underscore is definitely bad practice, as may collides with the standard library/compiler internals, see C 7.1.3:

All identifiers that begin with an underscore are always reserved for use as identifiers with file scope in both the ordinary and tag name spaces.

The most common practice is actually not to use a struct tag at all. There are just a few special cases where they are actually needed, such as self-referencing structs and opaque types etc. Based on that I'd subjectively say that either of these are "best":

typedef struct {...} ll_item;
typedef struct ll_item {...} ll_item;

Because both struct ll_item (struct tag version) and ll_item (typedef version) refers to the same object type, even though they happen to exist in different namespaces. struct ll_item and ll_item are compatible types.

A self-referencing struct would then look like:

typedef struct ll_item 
{
  ...
  struct ll_item* next;
} ll_item;

An opaque type forward declaration would look like:

typedef struct ll_item ll_item;

And an opaque type definition (private) will then not use typedef but refer to the same type:

struct ll_item { ... };

As for naming, that's just according to your coding standard. ll_item_type would be fine too, and even ll_item_t if you don't care about POSIX.

Lundin
  • 195,001
  • 40
  • 254
  • 396
  • I prefer to name the struct, i.e. `typedef struct ll_item {...} ll_item;` because in some cases compiler error/warning messages may refer to the struct name and if the struct is unnamed the message will say something like "... struct ...". Perhaps this was mostly an issue with older compilers. – nielsen Jun 09 '23 at 11:43