2

Possible Duplicate:
typedef struct vs struct definitions

Recently I'm reading nginx source code. There were so many structures defined as

typedef struct {
    field_1;
    field_2;
    /* ... */
} some_obj_t;

but there were still some other structures defined as

struct some_obj_s {
    field_1;
    field_2;
    /* ... */
};

Then, in some other header file, such as ngx_core.h, do some typedef:

typedef struct some_obj_s some_obj_t;

My question is (maybe duplicated...):

  • Why do authors not use the same form to define all structures?
  • In which case(s) should we use typedef on a struct definition? Is there any OO or design pattern considerations?
Community
  • 1
  • 1
coanor
  • 3,746
  • 4
  • 50
  • 67
  • Can you please elaborate on your first question? _Why author do not use the union form to define structure?_ – mihirj Oct 10 '12 at 05:03
  • @mihirj: Fixed, thanks for your advising. – coanor Oct 10 '12 at 05:10
  • According to Linus Torvalds, you should never typedef structures in order to maintain readability. –  Oct 10 '12 at 05:14
  • As I know, do not use `typedef` is to avoid pollution to the global namespace for LARGE C program, but nginx used the `ngx_` prefix to avoid the pollution, so I think it's `typedef` is clean. – coanor Oct 10 '12 at 05:20
  • My suspicion is simply that the code was authored by multiple people with different habits. There's no advantage to *not* typedefing a struct that I know of. – j_random_hacker Oct 10 '12 at 05:30

4 Answers4

3

You use typedef on a structure mainly as a matter of convenience. For example:

typedef struct List_
{
    ...

} List;

This allows you to define variables of type List simply as:

List myList;

instead of:

struct List_ myList;

All those extra struct statements clutter up your code. The other use of typedef as you show it, is to implement one type as another. For example:

typedef List Queue;

This defines a new type Queue to be a previously defined type List. This then allows you to use Queue as you would use List.

Nocturno
  • 9,579
  • 5
  • 31
  • 39
1

The different uses reflect whether the type is used in interfaces (only), or whether the structure information must be known.

The notation:

typedef struct some_obj_s some_obj_t;

tells the compiler that there's a structure type with tag some_obj_s and typedef name some_obj_t. If this type is an opaque type for users, there's no need to specify the details of the structure. Functions that take a some_obj_t * parameter (possibly qualified) or return such values can be declared and used without further information. (You can even declare extern variables of this sort of type since the compiler mainly needs an address.) The type is incomplete (also known as opaque), but can be completed.

Somewhere in the implementation, you'd find a definition of the structure type (except in the most unusual of circumstances), such as:

struct some_obj_s
{
    ...members defined...
};

Where this declaration (definition) is in scope, you can create variables of type some_obj_t or struct some_obj_s, as well as pointers to the type. The code can use the members of the structure.

The notation:

typedef struct /* no tag */
{
    ...
} another_obj_t;

defines a tagless struct type. The details of the type are provided, so the type is complete.

You may also see:

typedef struct yao_s
{
   ...members defined...
} yao_t;

This both declares the structure type with its tag and the typedef.

The separate typedef has an advantage with self-referencing structures, such as lists:

typedef struct GenericList GenericList;
struct GenericList
{
    void        *data;
    GenericList *next;
    GenericList *prev;
};

Without the separate typedef line, you'd have to write struct GenericList inside the structure. It means the same thing; you could still write it; but with the separate typedef, you can use the same notation in the structure as you will use later referring to it.

Note that POSIX reserves type names ending _t for the implementation. That means it can be dangerous to use that convention in your own code.

There is no need to use separate names for the tag and typedef (as demonstrated by the GenericList example), though the _s and _t suffixes are a fairly well known convention too. C++ automatically makes the tag into a type name without needing an explicit typedef (but the explicit typedef is allowed), so I usually use the same name for tag and type.

Community
  • 1
  • 1
Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
  • I'm afraid I don't see how only-used-in-interfaces-ness influences the decision of whether to use `typedef` or not. If the type is used only in an interface, either a plain forward declaration (`struct foo_s;`) or a typedef (`typedef struct foo_s foo_t;`) will work fine; if we need to know the size and/or access the internals of the type, again, either a plain declaration (`struct foo_s { ... };`) or a typedef of an unnamed struct (`typedef struct { ... } foo_t;`) will work fine. – j_random_hacker Oct 10 '12 at 05:28
  • What are we about to argue about? You're basically describing what I was trying to describe... – Jonathan Leffler Oct 10 '12 at 05:33
  • AFAICT the question is "Why use typedef'ed structs only sometimes?", and your answer is "Here is why you might want to use incomplete types only sometimes". – j_random_hacker Oct 10 '12 at 07:19
0

Why do authors not use the same form to define all structures?

Because they have adopted a certain coding style.

For example, the Linux kernel coding standard uses the struct notation without typedefs. That's pure coding style, they have no convincing rationale for why they do it, they just believe that 'struct' all over the code improves readability, since they think typedef "hides away the type".

Others don't agree, for example the Windows API uses the typedef notation all over, and never the struct one. I would say that this coding style is far more common, since it reminds a lot of the style of languages with OO support: C++, Java, C# etc.

No form can easily be proven correct over the other, it is all wonderfully subjective. Like most coding style matters.

In which case(s) should we use typedef on a struct definition? Is there any OO or design pattern considerations?

Indeed there is. There is something in C known as opaque or incomplete type, which allows you to implement true private encapsulation of variables. See this example I posted yesterday.

In that example there is typedef struct vector vector; in the header file, which basically creates an abstract base class: an object that the caller can create pointers to, but can't allocate. The caller will never be able to access the struct members.

Then in the .c file, there is an implementation of the struct as struct vector { ... }; which is only visible to the .c file and not to the caller.

Community
  • 1
  • 1
Lundin
  • 195,001
  • 40
  • 254
  • 396
  • (As a side note rant, I think the Linux kernal coding standard is very obscure and poorly written. If you compare it to well-written coding standards such as MISRA-C and CERT-C, it becomes blatantly obvious how unprofessional and unscientific the Linux standard is. The only reason I bring this rant up here, is because I wouldn't want it to seem as if I recommend anyone to adopt the Linux standard.) – Lundin Oct 10 '12 at 06:56
  • I was with you up to the point where you said that `typedef` can be used to create an opaque type. `typedef` isn't needed for this -- just a plain forward declaration (`struct foo;`) suffices. Of course the client code will then need to write `struct` everywhere, but that's the only difference -- encapsulation is preserved. – j_random_hacker Oct 10 '12 at 07:30
  • @j_random_hacker That might have been unclear indeed. My point was, if you don't use typedef, your will give you the caller the _useless knowledge_: "aha so this is implemented as a struct internally". Why would the caller care, that useless information goes against the OO principle of private encapsulation. It is just like providing the caller the type of private variables, it doesn't make sense. – Lundin Oct 10 '12 at 08:04
  • I suppose it does tell you that it's "a struct" -- but knowing that something is "a struct" literally tells you nothing about it :-P I mean, the client can look in the header file containing the `typedef` anyway! I don't see how encapsulation is reduced, since the only breaking change I can foresee happening would be if the library provider later wanted to change the the type to some fundamental type like `int`... but then, they would lose nothing by wrapping it in a struct. – j_random_hacker Oct 10 '12 at 08:21
-1

Please find answer to your second question by following the link below:

Why should we typedef a struct so often in C?

Community
  • 1
  • 1
mihirj
  • 1,199
  • 9
  • 15