Why should we typedef a struct so often in C?

后端 未结 15 2932
無奈伤痛
無奈伤痛 2020-11-21 23:58

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

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

elem user;

Why is i

15条回答
  •  我寻月下人不归
    2020-11-22 00:05

    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.

提交回复
热议问题