Why should we typedef a struct so often in C?

2018-12-31 04:57发布

I have seen many programs consisting of structures like the one below

typedef struct 
{
    int i;
    char k;
} elem;

elem user;

Why is it needed so often? Any specific reason or applicable area?

标签: c struct typedef
15条回答
听够珍惜
2楼-- · 2018-12-31 05:26

Let's start with the basics and work our way up.

Here is an example of Structure definition:

struct point
  {
    int x, y;
  };

Here the name point is optional.

A Structure can be declared during its definition or after.

Declaring during definition

struct point
  {
    int x, y;
  } first_point, second_point;

Declaring after definition

struct point
  {
    int x, y;
  };
struct point first_point, second_point;

Now, carefully note the last case above; you need to write struct point to declare Structures of that type if you decide to create that type at a later point in your code.

Enter typedef. If you intend to create new Structure ( Structure is a custom data-type) at a later time in your program using the same blueprint, using typedef during its definition might be a good idea since you can save some typing moving forward.

typedef struct point
  {
    int x, y;
  } Points;

Points first_point, second_point;

A word of caution while naming your custom type

Nothing prevents you from using _t suffix at the end of your custom type name but POSIX standard reserves the use of suffix _t to denote standard library type names.

查看更多
荒废的爱情
3楼-- · 2018-12-31 05:27

I don't think forward declarations are even possible with typedef. Use of struct, enum, and union allow for forwarding declarations when dependencies (knows about) is bidirectional.

Style: Use of typedef in C++ makes quite a bit of sense. It can almost be necessary when dealing with templates that require multiple and/or variable parameters. The typedef helps keep the naming straight.

Not so in the C programming language. The use of typedef most often serves no purpose but to obfuscate the data structure usage. Since only { struct (6), enum (4), union (5) } number of keystrokes are used to declare a data type there is almost no use for the aliasing of the struct. Is that data type a union or a struct? Using the straightforward non-typdefed declaration lets you know right away what type it is.

Notice how Linux is written with strict avoidance of this aliasing nonsense typedef brings. The result is a minimalist and clean style.

查看更多
有味是清欢
4楼-- · 2018-12-31 05:29

From an old article by Dan Saks (http://www.ddj.com/cpp/184403396?pgno=3):


The C language rules for naming structs are a little eccentric, but they're pretty harmless. However, when extended to classes in C++, those same rules open little cracks for bugs to crawl through.

In C, the name s appearing in

struct s
    {
    ...
    };

is a tag. A tag name is not a type name. Given the definition above, declarations such as

s x;    /* error in C */
s *p;   /* error in C */

are errors in C. You must write them as

struct s x;     /* OK */
struct s *p;    /* OK */

The names of unions and enumerations are also tags rather than types.

In C, tags are distinct from all other names (for functions, types, variables, and enumeration constants). C compilers maintain tags in a symbol table that's conceptually if not physically separate from the table that holds all other names. Thus, it is possible for a C program to have both a tag and an another name with the same spelling in the same scope. For example,

struct s s;

is a valid declaration which declares variable s of type struct s. It may not be good practice, but C compilers must accept it. I have never seen a rationale for why C was designed this way. I have always thought it was a mistake, but there it is.

Many programmers (including yours truly) prefer to think of struct names as type names, so they define an alias for the tag using a typedef. For example, defining

struct s
    {
    ...
    };
typedef struct s S;

lets you use S in place of struct s, as in

S x;
S *p;

A program cannot use S as the name of both a type and a variable (or function or enumeration constant):

S S;    // error

This is good.

The tag name in a struct, union, or enum definition is optional. Many programmers fold the struct definition into the typedef and dispense with the tag altogether, as in:

typedef struct
    {
    ...
    } S;

The linked article also has a discussion about how the C++ behavior of not requireing a typedef can cause subtle name hiding problems. To prevent these problems, it's a good idea to typedef your classes and structs in C++, too, even though at first glance it appears to be unnecessary. In C++, with the typedef the name hiding become an error that the compiler tells you about rather than a hidden source of potential problems.

查看更多
深知你不懂我心
5楼-- · 2018-12-31 05:29

the name you (optionally) give the struct is called the tag name and, as has been noted, is not a type in itself. To get to the type requires the struct prefix.

GTK+ aside, I'm not sure the tagname is used anything like as commonly as a typedef to the struct type, so in C++ that is recognised and you can omit the struct keyword and use the tagname as the type name too:


    struct MyStruct
    {
      int i;
    };

    // The following is legal in C++:
    MyStruct obj;
    obj.i = 7;

查看更多
路过你的时光
6楼-- · 2018-12-31 05:29

typedef will not provide a co-dependent set of data structures. This you cannot do with typdef:

struct bar;
struct foo;

struct foo {
    struct bar *b;
};

struct bar {
    struct foo *f;
};

Of course you can always add:

typedef struct foo foo_t;
typedef struct bar bar_t;

What exactly is the point of that?

查看更多
像晚风撩人
7楼-- · 2018-12-31 05:33

One other good reason to always typedef enums and structs results from this problem:

enum EnumDef
{
  FIRST_ITEM,
  SECOND_ITEM
};

struct StructDef
{
  enum EnuumDef MyEnum;
  unsigned int MyVar;
} MyStruct;

Notice the typo in EnumDef in the struct (EnuumDef)? This compiles without error (or warning) and is (depending on the literal interpretation of the C Standard) correct. The problem is that I just created an new (empty) enumeration definition within my struct. I am not (as intended) using the previous definition EnumDef.

With a typdef similar kind of typos would have resulted in a compiler errors for using an unknown type:

typedef 
{
  FIRST_ITEM,
  SECOND_ITEM
} EnumDef;

typedef struct
{
  EnuumDef MyEnum; /* compiler error (unknown type) */
  unsigned int MyVar;
} StructDef;
StrructDef MyStruct; /* compiler error (unknown type) */

I would advocate ALWAYS typedef'ing structs and enumerations.

Not only to save some typing (no pun intended ;)), but because it is safer.

查看更多
登录 后发表回答