Why should we typedef a struct so often in C?

后端 未结 15 2912
無奈伤痛
無奈伤痛 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:18

    It turns out that there are pros and cons. A useful source of information is the seminal book "Expert C Programming" (Chapter 3). Briefly, in C you have multiple namespaces: tags, types, member names and identifiers. typedef introduces an alias for a type and locates it in the tag namespace. Namely,

    typedef struct Tag{
    ...members...
    }Type;
    

    defines two things. One Tag in the tag namespace and one Type in the type namespace. So you can do both Type myType and struct Tag myTagType. Declarations like struct Type myType or Tag myTagType are illegal. In addition, in a declaration like this:

    typedef Type *Type_ptr;
    

    we define a pointer to our Type. So if we declare:

    Type_ptr var1, var2;
    struct Tag *myTagType1, myTagType2;
    

    then var1,var2 and myTagType1 are pointers to Type but myTagType2 not.

    In the above-mentioned book, it mentions that typedefing structs are not very useful as it only saves the programmer from writing the word struct. However, I have an objection, like many other C programmers. Although it sometimes turns to obfuscate some names (that's why it is not advisable in large code bases like the kernel) when you want to implement polymorphism in C it helps a lot look here for details. Example:

    typedef struct MyWriter_t{
        MyPipe super;
        MyQueue relative;
        uint32_t flags;
    ...
    }MyWriter;
    

    you can do:

    void my_writer_func(MyPipe *s)
    {
        MyWriter *self = (MyWriter *) s;
        uint32_t myFlags = self->flags;
    ...
    }
    

    So you can access an outer member (flags) by the inner struct (MyPipe) through casting. For me it is less confusing to cast the whole type than doing (struct MyWriter_ *) s; every time you want to perform such functionality. In these cases brief referencing is a big deal especially if you heavily employ the technique in your code.

    Finally, the last aspect with typedefed types is the inability to extend them, in contrast to macros. If for example, you have:

    #define X char[10] or
    typedef char Y[10]
    

    you can then declare

    unsigned X x; but not
    unsigned Y y;
    

    We do not really care for this for structs because it does not apply to storage specifiers (volatile and const).

提交回复
热议问题