Why should we typedef a struct so often in C?

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

    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.

    0 讨论(0)
  • 2020-11-22 00:03

    As Greg Hewgill said, the typedef means you no longer have to write struct all over the place. That not only saves keystrokes, it also can make the code cleaner since it provides a smidgen more abstraction.

    Stuff like

    typedef struct {
      int x, y;
    } Point;
    
    Point point_new(int x, int y)
    {
      Point a;
      a.x = x;
      a.y = y;
      return a;
    }
    

    becomes cleaner when you don't need to see the "struct" keyword all over the place, it looks more as if there really is a type called "Point" in your language. Which, after the typedef, is the case I guess.

    Also note that while your example (and mine) omitted naming the struct itself, actually naming it is also useful for when you want to provide an opaque type. Then you'd have code like this in the header, for instance:

    typedef struct Point Point;
    
    Point * point_new(int x, int y);
    

    and then provide the struct definition in the implementation file:

    struct Point
    {
      int x, y;
    };
    
    Point * point_new(int x, int y)
    {
      Point *p;
      if((p = malloc(sizeof *p)) != NULL)
      {
        p->x = x;
        p->y = y;
      }
      return p;
    }
    

    In this latter case, you cannot return the Point by value, since its definition is hidden from users of the header file. This is a technique used widely in GTK+, for instance.

    UPDATE Note that there are also highly-regarded C projects where this use of typedef to hide struct is considered a bad idea, the Linux kernel is probably the most well-known such project. See Chapter 5 of The Linux Kernel CodingStyle document for Linus' angry words. :) My point is that the "should" in the question is perhaps not set in stone, after all.

    0 讨论(0)
  • 2020-11-22 00:04

    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?

    0 讨论(0)
  • 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.

    0 讨论(0)
  • 2020-11-22 00:06

    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.

    0 讨论(0)
  • 2020-11-22 00:08

    In 'C' programming language the keyword 'typedef' is used to declare a new name for some object(struct, array, function..enum type). For example, I will use a 'struct-s'. In 'C' we often declare a 'struct' outside of the 'main' function. For example:

    struct complex{ int real_part, img_part }COMPLEX;
    
    main(){
    
     struct KOMPLEKS number; // number type is now a struct type
     number.real_part = 3;
     number.img_part = -1;
     printf("Number: %d.%d i \n",number.real_part, number.img_part);
    
    }
    

    Each time I decide to use a struct type I will need this keyword 'struct 'something' 'name'.'typedef' will simply rename that type and I can use that new name in my program every time I want. So our code will be:

    typedef struct complex{int real_part, img_part; }COMPLEX;
    //now COMPLEX is the new name for this structure and if I want to use it without
    // a keyword like in the first example 'struct complex number'.
    
    main(){
    
    COMPLEX number; // number is now the same type as in the first example
    number.real_part = 1;
    number.img)part = 5;
    printf("%d %d \n", number.real_part, number.img_part);
    
    }
    

    If you have some local object(struct, array, valuable) that will be used in your entire program you can simply give it a name using a 'typedef'.

    0 讨论(0)
提交回复
热议问题